Skip to content

Commit 4e89b5a

Browse files
committed
Add initial project structure, including CI/CD pipeline, CodeQL analysis, and central package management
- Introduced .editorconfig for consistent coding styles - Set up dependabot for automatic package updates - Created CI/CD workflow for build, test, and publish processes - Implemented CodeQL security analysis workflow - Added Directory.Packages.props for centralized package version management - Included MIT license file - Updated project files to support multi-target frameworks and enhanced metadata - Enhanced CountryDataLoader and Country models with XML documentation
1 parent bb71f2e commit 4e89b5a

11 files changed

Lines changed: 723 additions & 4 deletions

File tree

.editorconfig

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
# top-most EditorConfig file
2+
root = true
3+
4+
# Default settings:
5+
[*]
6+
indent_style = space
7+
trim_trailing_whitespace = true
8+
trim_trailing_white_space_on_save = true
9+
end_of_line = crlf
10+
11+
# Code files
12+
[*.{cs,vb}]
13+
indent_style = tab
14+
15+
[*.cs]
16+
# New line preferences
17+
csharp_new_line_before_open_brace = none
18+
csharp_new_line_before_else = true
19+
csharp_new_line_before_catch = true
20+
csharp_new_line_before_finally = true
21+
csharp_new_line_before_members_in_object_initializers = true
22+
csharp_new_line_before_members_in_anonymous_types = true
23+
csharp_new_line_within_query_expression_clauses = true
24+
25+
# Space preferences
26+
csharp_space_after_cast = false
27+
csharp_space_after_colon_in_inheritance_clause = true
28+
csharp_space_after_comma = true
29+
csharp_space_after_dot = false
30+
csharp_space_after_keywords_in_control_flow_statements = true
31+
csharp_space_after_semicolon_in_for_statement = true
32+
csharp_space_around_binary_operators = before_and_after
33+
csharp_space_around_declaration_statements = do_not_ignore
34+
csharp_space_before_colon_in_inheritance_clause = true
35+
csharp_space_before_comma = false
36+
csharp_space_before_dot = false
37+
csharp_space_before_open_square_brackets = false
38+
csharp_space_before_semicolon_in_for_statement = false
39+
csharp_space_between_empty_square_brackets = false
40+
csharp_space_between_method_call_empty_parameter_list_parentheses = false
41+
csharp_space_between_method_call_name_and_opening_parenthesis = false
42+
csharp_space_between_method_call_parameter_list_parentheses = false
43+
csharp_space_between_method_declaration_empty_parameter_list_parentheses = false
44+
csharp_space_between_method_declaration_name_and_open_parenthesis = false
45+
csharp_space_between_method_declaration_parameter_list_parentheses = false
46+
csharp_space_between_parentheses = false
47+
csharp_space_between_square_brackets = false
48+
49+
# Instance fields are camelCase and start with m_
50+
dotnet_naming_rule.camel_case_for_private_internal_fields.severity = silent
51+
dotnet_naming_rule.camel_case_for_private_internal_fields.symbols = private_internal_fields
52+
dotnet_naming_rule.camel_case_for_private_internal_fields.style = camel_case_underscore_style
53+
54+
dotnet_naming_symbols.private_internal_fields.applicable_kinds = field
55+
dotnet_naming_symbols.private_internal_fields.applicable_accessibilities = private, internal
56+
57+
dotnet_naming_style.camel_case_underscore_style.required_prefix = m_
58+
dotnet_naming_style.camel_case_underscore_style.capitalization = camel_case
59+
60+
# Locals and parameters are camelCase
61+
dotnet_naming_rule.locals_should_be_camel_case.severity = error
62+
dotnet_naming_rule.locals_should_be_camel_case.symbols = locals_and_parameters
63+
dotnet_naming_rule.locals_should_be_camel_case.style = camel_case_style
64+
65+
dotnet_naming_symbols.locals_and_parameters.applicable_kinds = parameter, local
66+
67+
dotnet_naming_style.camel_case_style.capitalization = camel_case
68+
69+
#### .NET naming conventions
70+
71+
# Async methods should have "Async" suffix
72+
dotnet_naming_rule.async_methods_end_in_async.symbols = any_async_methods
73+
dotnet_naming_rule.async_methods_end_in_async.style = end_in_async
74+
dotnet_naming_rule.async_methods_end_in_async.severity = suggestion
75+
76+
dotnet_naming_symbols.any_async_methods.applicable_kinds = method
77+
dotnet_naming_symbols.any_async_methods.applicable_accessibilities = *
78+
dotnet_naming_symbols.any_async_methods.required_modifiers = async
79+
80+
dotnet_naming_style.end_in_async.required_suffix = Async
81+
dotnet_naming_style.end_in_async.capitalization = pascal_case
82+
83+
# private variables should be underscored
84+
dotnet_naming_rule.private_members_with_underscore.symbols = private_fields
85+
dotnet_naming_rule.private_members_with_underscore.style = prefix_underscore
86+
dotnet_naming_rule.private_members_with_underscore.severity = suggestion
87+
88+
dotnet_naming_symbols.private_fields.applicable_kinds = field
89+
dotnet_naming_symbols.private_fields.applicable_accessibilities = private
90+
91+
dotnet_naming_style.prefix_underscore.capitalization = camel_case
92+
dotnet_naming_style.prefix_underscore.required_prefix = _

.github/dependabot.yml

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
version: 2
2+
updates:
3+
# Keep NuGet packages updated
4+
- package-ecosystem: "nuget"
5+
directory: "/"
6+
schedule:
7+
interval: "weekly" # Check weekly (not daily - less noise)
8+
day: "monday"
9+
time: "09:00"
10+
# Group related packages together in one PR
11+
groups:
12+
# Microsoft Extensions packages
13+
microsoft-extensions:
14+
patterns:
15+
- "Microsoft.Extensions.*"
16+
# Testing packages
17+
testing:
18+
patterns:
19+
- "xunit"
20+
- "xunit.*"
21+
- "FluentAssertions"
22+
- "Microsoft.NET.Test.Sdk"
23+
- "coverlet.*"
24+
# Build tools
25+
build-tools:
26+
patterns:
27+
- "Microsoft.SourceLink.*"
28+
- "MinVer"
29+
# Limit open PRs (avoid spam)
30+
open-pull-requests-limit: 5
31+
32+
# Keep GitHub Actions updated
33+
- package-ecosystem: "github-actions"
34+
directory: "/"
35+
schedule:
36+
interval: "monthly" # Actions don't change often
37+
open-pull-requests-limit: 3

.github/workflows/ci-cd.yml

Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
name: CI/CD Pipeline
2+
3+
on:
4+
push:
5+
branches: [ develop, master ]
6+
tags:
7+
- 'v*'
8+
pull_request:
9+
branches: [ develop, master ]
10+
11+
env:
12+
DOTNET_VERSION: '10.0.x'
13+
CONFIGURATION: Release
14+
DOTNET_NOLOGO: true
15+
DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true
16+
MINVERBUILDMETADATA: build.${{ github.run_number }}
17+
MINVERVERBOSITY: diagnostic
18+
19+
jobs:
20+
build-and-test:
21+
name: Build and Test
22+
runs-on: ubuntu-latest
23+
24+
steps:
25+
- name: Checkout code
26+
uses: actions/checkout@v5
27+
with:
28+
fetch-depth: 0 # Full history for versioning
29+
ref: ${{ github.ref }} # Checkout the exact ref (tag or branch)
30+
31+
- name: Setup .NET
32+
uses: actions/setup-dotnet@v4
33+
with:
34+
dotnet-version: ${{ env.DOTNET_VERSION }}
35+
36+
- name: Verify Git tags for MinVer
37+
run: |
38+
git fetch --tags --force
39+
git describe --tags
40+
git tag --points-at HEAD
41+
42+
- name: Restore dependencies
43+
run: dotnet restore
44+
45+
- name: Build library projects
46+
run: |
47+
dotnet build src/CountryData.Globalization/CountryData.Globalization.csproj --configuration ${{ env.CONFIGURATION }} --no-restore
48+
dotnet build src/CountryData.Globalization.Hosting/CountryData.Globalization.Hosting.csproj --configuration ${{ env.CONFIGURATION }} --no-restore
49+
dotnet build tests/CountryData.Globalization.Tests/CountryData.Globalization.Tests.csproj --configuration ${{ env.CONFIGURATION }} --no-restore
50+
51+
- name: Run tests
52+
run: dotnet test --configuration ${{ env.CONFIGURATION }} --no-build --verbosity normal --logger "trx;LogFileName=test-results.trx"
53+
54+
- name: Upload test results
55+
if: always()
56+
uses: actions/upload-artifact@v4
57+
with:
58+
name: test-results
59+
path: '**/TestResults/*.trx'
60+
61+
- name: Pack NuGet packages
62+
if: github.event_name == 'push' && (github.ref == 'refs/heads/develop' || github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/tags/v'))
63+
run: |
64+
dotnet pack src/CountryData.Globalization/CountryData.Globalization.csproj --configuration ${{ env.CONFIGURATION }} --no-build --output ./artifacts
65+
dotnet pack src/CountryData.Globalization.Hosting/CountryData.Globalization.Hosting.csproj --configuration ${{ env.CONFIGURATION }} --no-build --output ./artifacts
66+
67+
- name: Upload NuGet artifacts
68+
if: github.event_name == 'push' && (github.ref == 'refs/heads/develop' || github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/tags/v'))
69+
uses: actions/upload-artifact@v4
70+
with:
71+
name: nuget-packages
72+
path: ./artifacts/*.nupkg
73+
74+
publish-develop:
75+
name: Publish to GitHub Packages (Develop)
76+
needs: build-and-test
77+
if: github.event_name == 'push' && github.ref == 'refs/heads/develop'
78+
runs-on: ubuntu-latest
79+
permissions:
80+
packages: write
81+
contents: read
82+
83+
steps:
84+
- name: Download NuGet artifacts
85+
uses: actions/download-artifact@v5
86+
with:
87+
name: nuget-packages
88+
path: ./artifacts
89+
90+
- name: Setup .NET
91+
uses: actions/setup-dotnet@v4
92+
with:
93+
dotnet-version: ${{ env.DOTNET_VERSION }}
94+
95+
- name: Publish to GitHub Packages
96+
run: |
97+
dotnet nuget add source --username ${{ github.repository_owner }} \
98+
--password ${{ secrets.GITHUB_TOKEN }} \
99+
--store-password-in-clear-text \
100+
--name github "https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json"
101+
102+
dotnet nuget push "./artifacts/*.nupkg" \
103+
--source "github" \
104+
--api-key ${{ secrets.GITHUB_TOKEN }} \
105+
--skip-duplicate
106+
107+
publish-release:
108+
name: Publish to NuGet.org (Release)
109+
needs: build-and-test
110+
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v')
111+
runs-on: ubuntu-latest
112+
113+
steps:
114+
- name: Download NuGet artifacts
115+
uses: actions/download-artifact@v5
116+
with:
117+
name: nuget-packages
118+
path: ./artifacts
119+
120+
- name: Setup .NET
121+
uses: actions/setup-dotnet@v4
122+
with:
123+
dotnet-version: ${{ env.DOTNET_VERSION }}
124+
125+
- name: Publish to NuGet.org
126+
run: |
127+
dotnet nuget push "./artifacts/*.nupkg" \
128+
--source https://api.nuget.org/v3/index.json \
129+
--api-key ${{ secrets.NUGET_API_KEY }} \
130+
--skip-duplicate
131+
env:
132+
NUGET_API_KEY: ${{ secrets.NUGET_API_KEY }}
133+
134+
create-release:
135+
name: Create GitHub Release
136+
needs: publish-release
137+
if: startsWith(github.ref, 'refs/tags/v')
138+
runs-on: ubuntu-latest
139+
permissions:
140+
contents: write
141+
142+
steps:
143+
- name: Checkout code
144+
uses: actions/checkout@v5
145+
146+
- name: Download NuGet artifacts
147+
uses: actions/download-artifact@v5
148+
with:
149+
name: nuget-packages
150+
path: ./artifacts
151+
152+
- name: Extract version from tag
153+
id: version
154+
run: echo "VERSION=${GITHUB_REF#refs/tags/v}" >> $GITHUB_OUTPUT
155+
156+
- name: Create Release
157+
uses: softprops/action-gh-release@v2
158+
with:
159+
name: Release ${{ steps.version.outputs.VERSION }}
160+
body: |
161+
## CountryData.Globalization v${{ steps.version.outputs.VERSION }}
162+
163+
### NuGet Packages Published
164+
165+
- ✅ CountryData.Globalization
166+
- ✅ CountryData.Globalization.Hosting
167+
168+
### Installation
169+
170+
```bash
171+
# Core package
172+
dotnet add package CountryData.Globalization
173+
174+
# Hosting package (for DI support)
175+
dotnet add package CountryData.Globalization.Hosting
176+
```
177+
178+
### What's Changed
179+
180+
See [CHANGELOG.md](CHANGELOG.md) for detailed release notes.
181+
files: ./artifacts/*.nupkg
182+
draft: false
183+
prerelease: false
184+
env:
185+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

.github/workflows/codeql.yml

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
name: CodeQL Security Analysis
2+
3+
on:
4+
push:
5+
branches: [ develop, master ]
6+
pull_request:
7+
branches: [ develop, master ]
8+
schedule:
9+
# Run weekly on Sundays at 4:43 AM UTC
10+
- cron: '43 4 * * 0'
11+
12+
permissions:
13+
actions: read
14+
contents: read
15+
security-events: write
16+
17+
jobs:
18+
analyze:
19+
name: Analyze C# Code
20+
runs-on: ubuntu-latest
21+
22+
steps:
23+
- name: Checkout repository
24+
uses: actions/checkout@v5
25+
26+
- name: Initialize CodeQL
27+
uses: github/codeql-action/init@v3
28+
with:
29+
languages: csharp
30+
# Use default queries + security-extended queries
31+
queries: security-extended
32+
33+
- name: Autobuild
34+
uses: github/codeql-action/autobuild@v3
35+
36+
- name: Perform CodeQL Analysis
37+
uses: github/codeql-action/analyze@v3

Directory.Packages.props

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<Project>
2+
<PropertyGroup>
3+
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
4+
<CentralPackageTransitivePinningEnabled>true</CentralPackageTransitivePinningEnabled>
5+
</PropertyGroup>
6+
7+
<!-- Build Tools -->
8+
<ItemGroup>
9+
<PackageVersion Include="MinVer" Version="6.0.0" />
10+
<PackageVersion Include="Microsoft.SourceLink.GitHub" Version="8.0.0" />
11+
</ItemGroup>
12+
13+
<!-- Microsoft Extensions -->
14+
<ItemGroup>
15+
<PackageVersion Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="9.0.0" />
16+
</ItemGroup>
17+
18+
<!-- Testing Packages -->
19+
<ItemGroup>
20+
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.12.0" />
21+
<PackageVersion Include="xunit" Version="2.9.2" />
22+
<PackageVersion Include="xunit.runner.visualstudio" Version="2.8.2" />
23+
<PackageVersion Include="coverlet.collector" Version="6.0.2" />
24+
<PackageVersion Include="FluentAssertions" Version="7.0.0" />
25+
</ItemGroup>
26+
27+
</Project>
File renamed without changes.

0 commit comments

Comments
 (0)