Skip to content

Commit 35274fb

Browse files
konardclaude
andcommitted
feat: reorganize repository with csharp and rust folders
This commit restructures the repository to support multiple language implementations: - Move C# code to csharp/ folder - Add Rust implementation in rust/ folder - Add separate workflows: csharp.yml and rust.yml - Add shared scripts/ folder with CI/CD automation scripts - Add changeset/changelog support for both languages Structure: - csharp/: C# implementation with NuGet publishing - rust/: Rust implementation with crates.io publishing - scripts/: Shared .mjs scripts for CI/CD automation - .github/workflows/: Language-specific workflows Both workflows are based on: - https://github.com/link-foundation/csharp-ai-driven-development-pipeline-template - https://github.com/link-foundation/rust-ai-driven-development-pipeline-template Fixes #63 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 44b0b4c commit 35274fb

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+3861
-26
lines changed

.github/workflows/csharp.yml

Lines changed: 339 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,362 @@
1-
name: C#
1+
name: C# CI/CD Pipeline
22

3-
# Trigger the workflow when a new tag is pushed
43
on:
54
push:
6-
tags:
7-
- 'v*' # This example triggers on tags like v1.0.0
5+
branches:
6+
- main
7+
paths:
8+
- 'csharp/**'
9+
- 'scripts/**'
10+
- '.github/workflows/csharp.yml'
11+
pull_request:
12+
types: [opened, synchronize, reopened]
13+
paths:
14+
- 'csharp/**'
15+
- 'scripts/**'
16+
- '.github/workflows/csharp.yml'
17+
workflow_dispatch:
18+
inputs:
19+
release_mode:
20+
description: 'Release mode'
21+
required: true
22+
type: choice
23+
default: 'instant'
24+
options:
25+
- instant
26+
- changeset-pr
27+
bump_type:
28+
description: 'Version bump type'
29+
required: true
30+
type: choice
31+
options:
32+
- patch
33+
- minor
34+
- major
35+
description:
36+
description: 'Release description (optional)'
37+
required: false
38+
type: string
39+
40+
concurrency:
41+
group: csharp-${{ github.workflow }}-${{ github.ref }}
42+
cancel-in-progress: true
43+
44+
env:
45+
DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true
46+
DOTNET_CLI_TELEMETRY_OPTOUT: true
47+
DOTNET_NOLOGO: true
48+
49+
defaults:
50+
run:
51+
working-directory: csharp
852

953
jobs:
10-
build-and-publish:
54+
# === DETECT CHANGES - determines which jobs should run ===
55+
detect-changes:
56+
name: Detect Changes
57+
runs-on: ubuntu-latest
58+
if: github.event_name != 'workflow_dispatch'
59+
outputs:
60+
cs-changed: ${{ steps.changes.outputs.cs-changed }}
61+
csproj-changed: ${{ steps.changes.outputs.csproj-changed }}
62+
sln-changed: ${{ steps.changes.outputs.sln-changed }}
63+
props-changed: ${{ steps.changes.outputs.props-changed }}
64+
mjs-changed: ${{ steps.changes.outputs.mjs-changed }}
65+
docs-changed: ${{ steps.changes.outputs.docs-changed }}
66+
workflow-changed: ${{ steps.changes.outputs.workflow-changed }}
67+
any-code-changed: ${{ steps.changes.outputs.any-code-changed }}
68+
csharp-code-changed: ${{ steps.changes.outputs.csharp-code-changed }}
69+
steps:
70+
- uses: actions/checkout@v4
71+
with:
72+
fetch-depth: 0
73+
74+
- name: Setup Node.js
75+
uses: actions/setup-node@v4
76+
with:
77+
node-version: '20.x'
78+
79+
- name: Detect changes
80+
id: changes
81+
working-directory: .
82+
env:
83+
GITHUB_EVENT_NAME: ${{ github.event_name }}
84+
GITHUB_BASE_SHA: ${{ github.event.pull_request.base.sha }}
85+
GITHUB_HEAD_SHA: ${{ github.event.pull_request.head.sha }}
86+
run: node scripts/detect-code-changes.mjs
87+
88+
# === CHANGESET CHECK - only runs on PRs with code changes ===
89+
changeset-check:
90+
name: Changeset Validation
1191
runs-on: ubuntu-latest
92+
needs: [detect-changes]
93+
if: github.event_name == 'pull_request' && needs.detect-changes.outputs.csharp-code-changed == 'true'
94+
steps:
95+
- uses: actions/checkout@v4
96+
with:
97+
fetch-depth: 0
98+
99+
- name: Setup Node.js
100+
uses: actions/setup-node@v4
101+
with:
102+
node-version: '20.x'
103+
104+
- name: Validate changeset
105+
working-directory: .
106+
env:
107+
GITHUB_BASE_REF: ${{ github.base_ref }}
108+
GITHUB_BASE_SHA: ${{ github.event.pull_request.base.sha }}
109+
GITHUB_HEAD_SHA: ${{ github.event.pull_request.head.sha }}
110+
run: |
111+
# Skip changeset check for automated release PRs
112+
if [[ "${{ github.head_ref }}" == "changeset-release/"* ]] || [[ "${{ github.head_ref }}" == "changeset-manual-release-"* ]]; then
113+
echo "Skipping changeset check for automated release PR"
114+
exit 0
115+
fi
116+
117+
# Check if changeset exists in csharp/.changeset
118+
CHANGESET_COUNT=$(find csharp/.changeset -name "*.md" ! -name "README.md" 2>/dev/null | wc -l)
119+
if [ "$CHANGESET_COUNT" -eq 0 ]; then
120+
echo "::warning::No changeset found in csharp/.changeset/. Please add a changeset for C# code changes."
121+
else
122+
echo "Found $CHANGESET_COUNT changeset file(s)"
123+
fi
124+
125+
# === LINT AND FORMAT CHECK ===
126+
lint:
127+
name: Lint and Format Check
128+
runs-on: ubuntu-latest
129+
needs: [detect-changes]
130+
if: |
131+
github.event_name == 'push' ||
132+
github.event_name == 'workflow_dispatch' ||
133+
needs.detect-changes.outputs.cs-changed == 'true' ||
134+
needs.detect-changes.outputs.csproj-changed == 'true' ||
135+
needs.detect-changes.outputs.sln-changed == 'true' ||
136+
needs.detect-changes.outputs.props-changed == 'true'
137+
steps:
138+
- uses: actions/checkout@v4
12139

140+
- name: Setup .NET
141+
uses: actions/setup-dotnet@v4
142+
with:
143+
dotnet-version: '8.0.x'
144+
145+
- name: Setup Node.js
146+
uses: actions/setup-node@v4
147+
with:
148+
node-version: '20.x'
149+
150+
- name: Restore dependencies
151+
run: dotnet restore
152+
153+
- name: Check formatting
154+
run: dotnet format --verify-no-changes --verbosity diagnostic
155+
156+
- name: Build with warnings as errors
157+
run: dotnet build --no-restore --configuration Release /warnaserror
158+
159+
- name: Check file size limit
160+
working-directory: .
161+
run: node scripts/check-file-size.mjs --lang csharp
162+
163+
# === TEST ON MULTIPLE OS ===
164+
test:
165+
name: Test (${{ matrix.os }})
166+
runs-on: ${{ matrix.os }}
167+
needs: [detect-changes, changeset-check]
168+
if: always() && (github.event_name == 'push' || github.event_name == 'workflow_dispatch' || needs.changeset-check.result == 'success' || needs.changeset-check.result == 'skipped')
169+
strategy:
170+
fail-fast: false
171+
matrix:
172+
os: [ubuntu-latest, macos-latest, windows-latest]
13173
steps:
14-
# Step 1: Checkout the repository
15-
- name: Checkout repository
16-
uses: actions/checkout@v3
174+
- uses: actions/checkout@v4
17175

18-
# Step 2: Setup .NET SDK
19176
- name: Setup .NET
20-
uses: actions/setup-dotnet@v3
177+
uses: actions/setup-dotnet@v4
21178
with:
22-
dotnet-version: '8.0.x' # Updated to match your project
179+
dotnet-version: '8.0.x'
23180

24-
# Step 3: Restore dependencies
25181
- name: Restore dependencies
26182
run: dotnet restore
27183

28-
# Step 4: Build the project
29184
- name: Build
30-
run: dotnet build --configuration Release --no-restore
185+
run: dotnet build --no-restore --configuration Release
31186

32-
# Step 5: Run tests (optional)
33-
- name: Test
34-
run: dotnet test --verbosity normal
187+
- name: Run tests
188+
run: dotnet test --no-build --configuration Release --verbosity normal --collect:"XPlat Code Coverage"
189+
190+
- name: Upload coverage to Codecov
191+
if: matrix.os == 'ubuntu-latest'
192+
uses: codecov/codecov-action@v4
193+
with:
194+
fail_ci_if_error: false
195+
196+
# === BUILD PACKAGE ===
197+
build:
198+
name: Build Package
199+
runs-on: ubuntu-latest
200+
needs: [lint, test]
201+
if: always() && needs.lint.result == 'success' && needs.test.result == 'success'
202+
steps:
203+
- uses: actions/checkout@v4
204+
205+
- name: Setup .NET
206+
uses: actions/setup-dotnet@v4
207+
with:
208+
dotnet-version: '8.0.x'
209+
210+
- name: Restore dependencies
211+
run: dotnet restore
35212

36-
# Step 6: Pack the NuGet package
37-
- name: Pack
38-
run: dotnet pack --configuration Release --no-build --output ./output
213+
- name: Build Release
214+
run: dotnet build --no-restore --configuration Release
215+
216+
- name: Pack NuGet package
217+
run: dotnet pack --no-build --configuration Release --output ./artifacts
218+
219+
- name: Upload artifacts
220+
uses: actions/upload-artifact@v4
221+
with:
222+
name: nuget-package
223+
path: csharp/artifacts/*.nupkg
224+
225+
# === AUTOMATIC RELEASE ===
226+
release:
227+
name: Release
228+
needs: [lint, test, build]
229+
if: always() && github.ref == 'refs/heads/main' && github.event_name == 'push' && needs.lint.result == 'success' && needs.test.result == 'success' && needs.build.result == 'success'
230+
runs-on: ubuntu-latest
231+
permissions:
232+
contents: write
233+
packages: write
234+
steps:
235+
- uses: actions/checkout@v4
236+
with:
237+
fetch-depth: 0
238+
239+
- name: Setup .NET
240+
uses: actions/setup-dotnet@v4
241+
with:
242+
dotnet-version: '8.0.x'
243+
244+
- name: Setup Node.js
245+
uses: actions/setup-node@v4
246+
with:
247+
node-version: '20.x'
248+
249+
- name: Check for changesets
250+
id: check_changesets
251+
working-directory: .
252+
run: |
253+
# Count changeset files (excluding README.md and config.json)
254+
CHANGESET_COUNT=$(find csharp/.changeset -name "*.md" ! -name "README.md" 2>/dev/null | wc -l)
255+
echo "Found $CHANGESET_COUNT changeset file(s)"
256+
echo "has_changesets=$([[ $CHANGESET_COUNT -gt 0 ]] && echo 'true' || echo 'false')" >> $GITHUB_OUTPUT
257+
echo "changeset_count=$CHANGESET_COUNT" >> $GITHUB_OUTPUT
258+
259+
- name: Merge multiple changesets
260+
if: steps.check_changesets.outputs.has_changesets == 'true' && steps.check_changesets.outputs.changeset_count > 1
261+
working-directory: .
262+
run: |
263+
echo "Multiple changesets detected, merging..."
264+
node scripts/merge-changesets.mjs --dir csharp/.changeset
265+
266+
- name: Version and commit
267+
if: steps.check_changesets.outputs.has_changesets == 'true'
268+
id: version
269+
working-directory: .
270+
run: node scripts/version-and-commit-csharp.mjs --mode changeset
271+
272+
- name: Download artifacts
273+
if: steps.version.outputs.version_committed == 'true'
274+
uses: actions/download-artifact@v4
275+
with:
276+
name: nuget-package
277+
path: ./artifacts
39278

40-
# Step 7: Publish the NuGet package
41279
- name: Publish to NuGet
280+
if: steps.version.outputs.version_committed == 'true'
42281
env:
43282
NUGET_API_KEY: ${{ secrets.NUGET_API_KEY }}
44283
run: |
45-
dotnet nuget push ./output/*.nupkg \
46-
--api-key $NUGET_API_KEY \
47-
--source https://api.nuget.org/v3/index.json \
48-
--skip-duplicate
284+
if [ -n "$NUGET_API_KEY" ]; then
285+
dotnet nuget push ../artifacts/*.nupkg --api-key $NUGET_API_KEY --source https://api.nuget.org/v3/index.json --skip-duplicate
286+
else
287+
echo "NUGET_API_KEY not set, skipping NuGet publish"
288+
fi
289+
290+
- name: Create GitHub Release
291+
if: steps.version.outputs.version_committed == 'true'
292+
env:
293+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
294+
working-directory: .
295+
run: |
296+
node scripts/create-github-release.mjs \
297+
--release-version "${{ steps.version.outputs.new_version }}" \
298+
--repository "${{ github.repository }}" \
299+
--tag-prefix "csharp-v"
300+
301+
# === MANUAL INSTANT RELEASE ===
302+
instant-release:
303+
name: Instant Release
304+
needs: [lint, test, build]
305+
if: github.event_name == 'workflow_dispatch' && github.event.inputs.release_mode == 'instant' && needs.lint.result == 'success' && needs.test.result == 'success' && needs.build.result == 'success'
306+
runs-on: ubuntu-latest
307+
permissions:
308+
contents: write
309+
packages: write
310+
steps:
311+
- uses: actions/checkout@v4
312+
with:
313+
fetch-depth: 0
314+
token: ${{ secrets.GITHUB_TOKEN }}
315+
316+
- name: Setup .NET
317+
uses: actions/setup-dotnet@v4
318+
with:
319+
dotnet-version: '8.0.x'
320+
321+
- name: Setup Node.js
322+
uses: actions/setup-node@v4
323+
with:
324+
node-version: '20.x'
325+
326+
- name: Version and commit
327+
id: version
328+
working-directory: .
329+
run: |
330+
node scripts/version-and-commit-csharp.mjs \
331+
--mode instant \
332+
--bump-type "${{ github.event.inputs.bump_type }}" \
333+
--description "${{ github.event.inputs.description }}"
334+
335+
- name: Build package
336+
if: steps.version.outputs.version_committed == 'true'
337+
run: |
338+
dotnet restore
339+
dotnet build --configuration Release
340+
dotnet pack --no-build --configuration Release --output ./artifacts
341+
342+
- name: Publish to NuGet
343+
if: steps.version.outputs.version_committed == 'true'
344+
env:
345+
NUGET_API_KEY: ${{ secrets.NUGET_API_KEY }}
346+
run: |
347+
if [ -n "$NUGET_API_KEY" ]; then
348+
dotnet nuget push ./artifacts/*.nupkg --api-key $NUGET_API_KEY --source https://api.nuget.org/v3/index.json --skip-duplicate
349+
else
350+
echo "NUGET_API_KEY not set, skipping NuGet publish"
351+
fi
352+
353+
- name: Create GitHub Release
354+
if: steps.version.outputs.version_committed == 'true'
355+
env:
356+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
357+
working-directory: .
358+
run: |
359+
node scripts/create-github-release.mjs \
360+
--release-version "${{ steps.version.outputs.new_version }}" \
361+
--repository "${{ github.repository }}" \
362+
--tag-prefix "csharp-v"

0 commit comments

Comments
 (0)