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
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
27 changes: 27 additions & 0 deletions .claude/skills/pipeline-rules/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
---
name: pipeline-rules
description: Backend (.NET) format, build, and test checks that mirror what CI enforces on this repo — dotnet format, a clean dotnet build, and dotnet test. Use whenever C# files under server/ are added, edited, or reviewed, before considering the work done.
metadata:
type: workflow
when_to_use: "finishing a backend change, editing a .cs file, before saying a server-side task is done, reviewing a C# diff, formatting check, dotnet build, dotnet test, dotnet format"
---

# Backend pipeline rules

Before treating any task that touches files under `server/` (not `server/.claude/worktrees/`) as finished, run the same checks CI would run — in this order, from the `server/` directory:

1. **Format** — `dotnet format`
Auto-fixes indentation, line length (120 cols), and other style rules from `.editorconfig`. Scope it to what you touched (e.g. `dotnet format --include <paths>`) rather than running it unscoped over the whole solution — an unscoped run reformats every file with pending changes anywhere in the repo, including other in-progress work that has nothing to do with your change. Use `dotnet format --verify-no-changes` instead if you only want to check without rewriting files.

Do not use `dotnet csharpier format`/`dotnet csharpier check` — this repo's CI enforces `dotnet format`/`.editorconfig`, not CSharpier.

2. **Build** — `dotnet build StackDuel.slnx`
Must succeed with no new errors. Don't introduce new warnings either, unless they're pre-existing and unrelated to the change.

3. **Test** — run whatever covers the change:
- Targeted: `dotnet test <Project> --filter "FullyQualifiedName~<Area>"` for a fast pass scoped to what changed.
- Full: `dotnet test StackDuel.slnx` when the change is broad, touches shared/domain code, or the blast radius is unclear.

Format first, then build, then test — a format pass can shift line numbers, so verify build/test against the formatted code, not before it.

Run this for every backend change, not only ones that look formatting-related. Code that compiles and passes tests but doesn't match `dotnet format`/`.editorconfig` conventions still fails CI.
13 changes: 13 additions & 0 deletions .config/dotnet-tools.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"version": 1,
"isRoot": true,
"tools": {
"csharpier": {
"version": "1.3.0",
"commands": [
"csharpier"
],
"rollForward": false
}
}
}
8 changes: 1 addition & 7 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -1,8 +1,2 @@
# Auto detect text files and perform LF normalization
* text=auto eol=lf

*.cs text eol=lf
*.csproj text eol=lf
*.slnx text eol=lf
*.json text eol=lf
*.yml text eol=lf
*.yaml text eol=lf
33 changes: 33 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
version: 2

updates:
- package-ecosystem: nuget
directory: /
schedule:
interval: weekly
day: monday
time: "06:00"
timezone: UTC
open-pull-requests-limit: 10
labels:
- dependencies
- dotnet
groups:
dotnet-patch:
update-types:
- patch
dotnet-minor:
update-types:
- minor

- package-ecosystem: github-actions
directory: /
schedule:
interval: weekly
day: monday
time: "06:00"
timezone: UTC
open-pull-requests-limit: 10
labels:
- dependencies
- github-actions
39 changes: 39 additions & 0 deletions .github/labeler.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Labels applied based on which paths changed in the PR.

area/infrastructure:
- changed-files:
- any-glob-to-any-file: 'StackDuel.Infrastructure/**'

area/domain:
- changed-files:
- any-glob-to-any-file: 'StackDuel.Domain/**'

area/api:
- changed-files:
- any-glob-to-any-file: 'StackDuel.Api/**'

area/application:
- changed-files:
- any-glob-to-any-file: 'StackDuel.Application/**'

area/tests:
- changed-files:
- any-glob-to-any-file: '**/*.Tests/**'
- any-glob-to-any-file: '**/*.Test/**'

area/seeder:
- changed-files:
- any-glob-to-any-file: 'StackDuel.Seeder/**'

ci/cd:
- changed-files:
- any-glob-to-any-file: '.github/**'
- any-glob-to-any-file: '**/Dockerfile*'
- any-glob-to-any-file: '**/*.yml'

configuration:
- changed-files:
- any-glob-to-any-file: '**/*.json'
- any-glob-to-any-file: '**/*.config'
- any-glob-to-any-file: '.editorconfig'
- any-glob-to-any-file: '.gitattributes'
77 changes: 77 additions & 0 deletions .github/workflows/auto-tag-release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
name: Auto Tag Release Branch

on:
create

permissions:
contents: write

concurrency:
group: auto-tag-release-${{ github.ref_name }}
cancel-in-progress: false

jobs:
tag:
if: github.ref_type == 'branch' && startsWith(github.ref, 'refs/heads/release/v')
runs-on: ubuntu-latest
timeout-minutes: 10
environment:
name: Production

steps:
- name: Checkout
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0
with:
ref: ${{ github.ref }}
fetch-depth: 0

- name: Extract and validate version from branch name
id: validate
shell: bash
env:
BRANCH: ${{ github.ref_name }}
run: |
set -euo pipefail

if ! [[ "${BRANCH}" =~ ^release/v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo "Branch name does not match release/vX.Y.Z: ${BRANCH}"
exit 1
fi

TAG="${BRANCH#release/}"
echo "tag=${TAG}" >> "$GITHUB_OUTPUT"

- name: Fail if tag already exists
shell: bash
env:
TAG: ${{ steps.validate.outputs.tag }}
run: |
set -euo pipefail

git fetch --tags
if git rev-parse "${TAG}" >/dev/null 2>&1; then
echo "Tag already exists: ${TAG}"
exit 1
fi

- name: Configure git
run: |
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"

- name: Create and push tag
shell: bash
env:
TAG: ${{ steps.validate.outputs.tag }}
run: |
set -euo pipefail

git tag -a "${TAG}" -m "Release ${TAG}"
git push origin "${TAG}"

- name: Publish GitHub Release
uses: softprops/action-gh-release@718ea10b132b3b2eba29c1007bb80653f286566b
with:
tag_name: ${{ steps.validate.outputs.tag }}
target_commitish: ${{ github.sha }}
generate_release_notes: true
50 changes: 50 additions & 0 deletions .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
name: CodeQL

on:
push:
branches:
- master
pull_request:
branches:
- master
schedule:
- cron: "0 6 * * 1"

permissions:
actions: read
contents: read
security-events: write

jobs:
analyze:
runs-on: ubuntu-latest
timeout-minutes: 30
strategy:
fail-fast: false
matrix:
language:
- csharp

steps:
- name: Checkout
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0

- name: Setup .NET SDK
uses: actions/setup-dotnet@v4
with:
dotnet-version: 10.0.x

- name: Initialize CodeQL
uses: github/codeql-action/init@v3
with:
languages: ${{ matrix.language }}
build-mode: manual

- name: Restore dependencies
run: dotnet restore StackDuel.slnx

- name: Build solution
run: dotnet build StackDuel.slnx -c Release --no-restore

- name: Perform CodeQL analysis
uses: github/codeql-action/analyze@v3
Loading
Loading