added nuget publish workflow
Some checks failed
Publish NuGet Packages / build-and-publish (push) Failing after 41s

This commit is contained in:
Mathias Beaulieu-Duncan 2025-10-06 15:12:38 -04:00
parent a7d2d8d872
commit 57c9aa6e00
8 changed files with 445 additions and 4 deletions

View File

@ -0,0 +1,69 @@
name: Publish NuGet Packages
on:
push:
tags:
- '[0-9]+.[0-9]+.[0-9]+'
- '[0-9]+.[0-9]+.[0-9]+-*'
jobs:
build-and-publish:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: '8.0.x'
- name: Extract version from tag
run: |
VERSION=${GITHUB_REF##*/}
echo "VERSION=$VERSION" >> $GITHUB_ENV
echo "Publishing version: $VERSION"
- name: Restore dependencies
run: dotnet restore
- name: Build solution
run: dotnet build --configuration Release --no-restore
- name: Run tests
run: dotnet test --configuration Release --no-build --verbosity normal
- name: Pack Abstractions
run: |
dotnet pack Svrnty.GeoManagement.Abstractions/Svrnty.GeoManagement.Abstractions.csproj \
--configuration Release \
--no-build \
--output ./artifacts \
-p:Version=${{ env.VERSION }}
- name: Pack Google Provider
run: |
dotnet pack Svrnty.GeoManagement.Google/Svrnty.GeoManagement.Google.csproj \
--configuration Release \
--no-build \
--output ./artifacts \
-p:Version=${{ env.VERSION }}
- name: List packages
run: ls -lh ./artifacts
- name: Publish to NuGet.org
run: |
dotnet nuget push ./artifacts/*.nupkg \
--api-key ${{ secrets.NUGET_API_KEY }} \
--source https://api.nuget.org/v3/index.json \
--skip-duplicate
- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: nuget-packages-${{ env.VERSION }}
path: ./artifacts/*.nupkg

View File

@ -8,10 +8,11 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
## Solution Structure
The solution contains two projects:
The solution contains these projects:
- **Svrnty.GeoManagement.Abstractions**: Core abstractions and models for geocoding operations
- **Svrnty.GeoManagement.Tests**: xUnit test project
- **Svrnty.GeoManagement.Abstractions**: Core abstractions and models for geocoding operations (published to NuGet)
- **Svrnty.GeoManagement.Google**: Google Geocoding API provider implementation (published to NuGet)
- **Svrnty.GeoManagement.Tests**: xUnit integration test project
## Key Architecture Patterns
@ -56,3 +57,56 @@ dotnet restore
- Nullable reference types are enabled
- The Abstractions project is designed to be provider-agnostic - don't add provider-specific dependencies
- When implementing `IGeoManagementProvider`, all methods support `CancellationToken` for async operations
## NuGet Package Publishing
### Published Packages
- **Svrnty.GeoManagement.Abstractions** - Core interfaces and models
- **Svrnty.GeoManagement.Google** - Google Maps API provider
### Release Process
1. **Ensure all changes are committed and pushed**
2. **Create and push a git tag** with the version number:
```bash
git tag 1.0.0
git push origin 1.0.0
```
3. **Tag format**:
- Stable releases: `1.0.0`, `1.2.3`
- Pre-releases: `1.0.0-alpha`, `1.0.0-beta.1`, `1.0.0-rc.2`
4. **Automated workflow** (`.gitea/workflows/publish-nuget.yml`):
- Triggers on any tag matching version pattern
- Runs all tests
- Builds Release configuration
- Packs both NuGet packages with the tag version
- Publishes to NuGet.org
### Version Management
- Package versions are automatically set from the git tag
- Default version in `.csproj` files is `0.1.0` (used only for local development)
- CI/CD overrides version with tag value during publish
### Prerequisites
- `NUGET_API_KEY` must be configured as a Gitea repository secret
- Tests must pass for publish to succeed
- Both packages are always published together with the same version
### Local Package Testing
To test package creation locally:
```bash
# Pack with custom version
dotnet pack Svrnty.GeoManagement.Abstractions -c Release -p:Version=1.0.0-test
# Pack Google provider
dotnet pack Svrnty.GeoManagement.Google -c Release -p:Version=1.0.0-test
# View generated packages
ls */bin/Release/*.nupkg
```

21
LICENSE Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2025 Svrnty
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

134
RELEASING.md Normal file
View File

@ -0,0 +1,134 @@
# Release Guide
This guide explains how to publish new versions of the Svrnty.GeoManagement NuGet packages.
## Prerequisites
✅ All tests passing
✅ Changes committed and pushed to main branch
`NUGET_API_KEY` configured in Gitea repository secrets
## Release Steps
### 1. Decide on Version Number
Follow [Semantic Versioning](https://semver.org/):
- **Major version** (x.0.0) - Breaking changes
- **Minor version** (0.x.0) - New features, backwards compatible
- **Patch version** (0.0.x) - Bug fixes, backwards compatible
**Pre-release suffixes:**
- `-alpha` - Early testing
- `-beta` - Feature complete, testing
- `-rc.1` - Release candidate
**Examples:**
- `1.0.0` - First stable release
- `1.1.0` - New features added
- `1.1.1` - Bug fix
- `2.0.0-beta.1` - Major version beta
### 2. Create and Push Git Tag
```bash
# Create tag (WITHOUT 'v' prefix)
git tag 1.0.0
# Push tag to trigger CI/CD
git push origin 1.0.0
```
### 3. Monitor Workflow
1. Go to your Gitea repository
2. Navigate to **Actions** tab
3. Watch the **"Publish NuGet Packages"** workflow run
4. Verify all steps complete successfully:
- ✅ Checkout code
- ✅ Setup .NET
- ✅ Build solution
- ✅ Run tests
- ✅ Pack packages
- ✅ Publish to NuGet.org
### 4. Verify on NuGet.org
After 5-10 minutes, check:
- https://www.nuget.org/packages/Svrnty.GeoManagement.Abstractions
- https://www.nuget.org/packages/Svrnty.GeoManagement.Google
## What Gets Published
Both packages are **always published together** with the same version:
1. **Svrnty.GeoManagement.Abstractions** - Core interfaces and models
2. **Svrnty.GeoManagement.Google** - Google provider implementation
## Workflow Details
The Gitea workflow (`.gitea/workflows/publish-nuget.yml`):
- **Trigger**: Any tag matching `[0-9]+.[0-9]+.[0-9]+*` pattern
- **Tag format**: Direct version number (e.g., `1.0.0`, not `v1.0.0`)
- **Quality gates**: Tests must pass before publish
- **Artifacts**: Packages uploaded to workflow artifacts for download
## Troubleshooting
### Workflow didn't trigger
- Verify tag format matches pattern (e.g., `1.0.0`, not `v1.0.0`)
- Check if tag was pushed: `git push origin --tags`
### Tests failed
- Run tests locally: `dotnet test`
- Fix issues and create new tag with next patch version
### Publish failed
- Check `NUGET_API_KEY` secret is configured in Gitea
- Verify API key has push permissions
- Check if version already exists on NuGet.org (use `--skip-duplicate`)
### Want to unpublish
- NuGet.org doesn't allow deletion, only unlisting
- Publish new patch version with fix instead
## Local Testing
Test package creation before releasing:
```bash
# Build Release configuration
dotnet build --configuration Release
# Create packages locally
dotnet pack Svrnty.GeoManagement.Abstractions -c Release -p:Version=1.0.0-local
dotnet pack Svrnty.GeoManagement.Google -c Release -p:Version=1.0.0-local
# Check package contents
dotnet nuget verify Svrnty.GeoManagement.Abstractions/bin/Release/*.nupkg
dotnet nuget verify Svrnty.GeoManagement.Google/bin/Release/*.nupkg
```
## Rollback a Release
If you need to rollback:
1. **Unlist the package** on NuGet.org (doesn't delete it)
2. **Publish a new patch version** with the fix
3. **Update documentation** to recommend the new version
## Version Increment Examples
Starting from `1.2.3`:
- Bug fix → `1.2.4`
- New feature → `1.3.0`
- Breaking change → `2.0.0`
- Beta for next major → `2.0.0-beta.1`
## Questions?
- Check workflow logs in Gitea Actions tab
- Review `CLAUDE.md` for development guidance
- See `TESTING.md` for test setup

View File

@ -56,6 +56,6 @@ public record Address(
return $"{Line1}\n{City}, {Subdivision} {PostalCode}\n{Country}";
}
return $"{Line2}\n{Line1}\n{City}, {Subdivision} {PostalCode}\n{Country}";
return $"{Line2}, {Line1}\n{City}, {Subdivision} {PostalCode}\n{Country}";
}
}

View File

@ -0,0 +1,123 @@
# Svrnty.GeoManagement.Abstractions
Core abstractions and models for geocoding and address management services.
## Overview
This package provides the foundational interfaces and data structures for implementing geocoding providers. It defines the contract for geocoding operations without being tied to any specific provider implementation.
## Installation
```bash
dotnet add package Svrnty.GeoManagement.Abstractions
```
## Key Components
### IGeoManagementProvider Interface
The main interface for geocoding operations:
```csharp
public interface IGeoManagementProvider
{
// Convert address to coordinates
Task<GeoPoint?> GetGeoPointAsync(Address address, CancellationToken cancellationToken = default);
// Convert coordinates to address
Task<Address?> ReverseGeocodeAsync(GeoPoint geoPoint, CancellationToken cancellationToken = default);
// Normalize and validate an address
Task<Address?> NormalizeAddressAsync(Address address, CancellationToken cancellationToken = default);
Task<Address?> NormalizeAddressAsync(string address, CancellationToken cancellationToken = default);
}
```
### Address Model
Represents a structured postal address:
```csharp
public record Address(
string Line1,
string? Line2,
string City,
string Subdivision, // State/Province
string PostalCode,
string Country,
GeoPoint? Location,
string? Note,
bool IsNormalized = false
);
```
Features:
- Formatted address output with `GetFormattedAddress()` method
- Support for multiple formats: Full, Compact, MultiLine
- Optional location coordinates
- Normalization tracking flag
### GeoPoint Model
Represents geographic coordinates:
```csharp
public record GeoPoint(double Latitude, double Longitude);
```
## Usage
This package is designed to be used with provider implementations. For example:
```csharp
using Svrnty.GeoManagement.Abstractions.Abstractions;
using Svrnty.GeoManagement.Abstractions.Models;
public class MyService
{
private readonly IGeoManagementProvider _geoProvider;
public MyService(IGeoManagementProvider geoProvider)
{
_geoProvider = geoProvider;
}
public async Task<GeoPoint?> GetCoordinates(Address address)
{
return await _geoProvider.GetGeoPointAsync(address);
}
}
```
## Available Providers
- **[Svrnty.GeoManagement.Google](https://www.nuget.org/packages/Svrnty.GeoManagement.Google)** - Google Maps Geocoding API implementation
## Implementing a Provider
To create your own geocoding provider:
1. Reference this package
2. Implement `IGeoManagementProvider`
3. Map provider-specific responses to `Address` and `GeoPoint` models
```csharp
public class MyCustomProvider : IGeoManagementProvider
{
public async Task<GeoPoint?> GetGeoPointAsync(Address address, CancellationToken cancellationToken = default)
{
// Your implementation
}
// ... implement other methods
}
```
## License
MIT License - see [LICENSE](https://git.openharbor.io/svrnty/dotnet-geo-management/blob/main/LICENSE) for details
## Links
- [Git Repository](https://git.openharbor.io/svrnty/dotnet-geo-management)
- [Google Provider Package](https://www.nuget.org/packages/Svrnty.GeoManagement.Google)

View File

@ -4,6 +4,26 @@
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<!-- NuGet Package Metadata -->
<PackageId>Svrnty.GeoManagement.Abstractions</PackageId>
<Authors>Svrnty</Authors>
<Company>Svrnty</Company>
<Product>Svrnty.GeoManagement</Product>
<Description>Core abstractions and models for geocoding and address management services. Provides interfaces and data structures for implementing geocoding providers.</Description>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<PackageProjectUrl>https://git.openharbor.io/svrnty/dotnet-geo-management</PackageProjectUrl>
<RepositoryUrl>https://git.openharbor.io/svrnty/dotnet-geo-management</RepositoryUrl>
<RepositoryType>git</RepositoryType>
<PackageTags>geocoding;address;geolocation;coordinates;gps;maps;abstractions</PackageTags>
<PackageReadmeFile>README.md</PackageReadmeFile>
<GeneratePackageOnBuild>false</GeneratePackageOnBuild>
<IncludeSymbols>true</IncludeSymbols>
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
</PropertyGroup>
<ItemGroup>
<None Include="README.md" Pack="true" PackagePath="\" />
</ItemGroup>
</Project>

View File

@ -15,6 +15,26 @@
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<!-- NuGet Package Metadata -->
<PackageId>Svrnty.GeoManagement.Google</PackageId>
<Authors>Svrnty</Authors>
<Company>Svrnty</Company>
<Product>Svrnty.GeoManagement</Product>
<Description>Google Geocoding API provider implementation for Svrnty.GeoManagement. Provides forward geocoding, reverse geocoding, and address normalization using Google Maps API.</Description>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<PackageProjectUrl>https://git.openharbor.io/svrnty/dotnet-geo-management</PackageProjectUrl>
<RepositoryUrl>https://git.openharbor.io/svrnty/dotnet-geo-management</RepositoryUrl>
<RepositoryType>git</RepositoryType>
<PackageTags>geocoding;google;google-maps;address;geolocation;coordinates;gps;maps</PackageTags>
<PackageReadmeFile>README.md</PackageReadmeFile>
<GeneratePackageOnBuild>false</GeneratePackageOnBuild>
<IncludeSymbols>true</IncludeSymbols>
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
</PropertyGroup>
<ItemGroup>
<None Include="README.md" Pack="true" PackagePath="\" />
</ItemGroup>
</Project>