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
155 changes: 155 additions & 0 deletions .github/workflows/NUGET_RELEASE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
# NuGet Release Workflow

This document describes the automated NuGet release workflow for SharpCompress.

## Overview

The `nuget-release.yml` workflow automatically builds, tests, and publishes SharpCompress packages to NuGet.org when:
- Changes are pushed to the `master` or `release` branch
- A version tag (format: `MAJOR.MINOR.PATCH`) is pushed

The workflow runs on both Windows and Ubuntu, but only the Windows build publishes to NuGet.

## How It Works

### Version Determination

The workflow automatically determines the version based on whether the commit is tagged using C# code in the build project:

1. **Tagged Release (Stable)**:
- If the current commit has a version tag (e.g., `0.42.1`)
- Uses the tag as the version number
- Published as a stable release

2. **Untagged Release (Prerelease)**:
- If the current commit is NOT tagged
- Creates a prerelease version based on the next minor version
- Format: `{NEXT_MINOR_VERSION}-beta.{COMMIT_COUNT}`
- Example: `0.43.0-beta.123` (if last tag is 0.42.x)
- Published as a prerelease to NuGet.org (Windows build only)

### Workflow Steps

The workflow runs on a matrix of operating systems (Windows and Ubuntu):

1. **Checkout**: Fetches the repository with full history for version detection
2. **Setup .NET**: Installs .NET 10.0
3. **Determine Version**: Runs `determine-version` build target to check for tags and determine version
4. **Update Version**: Runs `update-version` build target to update the version in the project file
5. **Build and Test**: Runs the full build and test suite on both platforms
6. **Upload Artifacts**: Uploads the generated `.nupkg` files as workflow artifacts (separate for each OS)
7. **Push to NuGet**: (Windows only) Runs `push-to-nuget` build target to publish the package to NuGet.org using the API key

All version detection, file updates, and publishing logic is implemented in C# in the `build/Program.cs` file using build targets.

## Setup Requirements

### 1. NuGet API Key Secret

The workflow requires a `NUGET_API_KEY` secret to be configured in the repository settings:

1. Go to https://www.nuget.org/account/apikeys
2. Create a new API key with "Push" permission for the SharpCompress package
3. In GitHub, go to: **Settings** → **Secrets and variables** → **Actions**
4. Create a new secret named `NUGET_API_KEY` with the API key value

### 2. Branch Protection (Recommended)

Consider enabling branch protection rules for the `release` branch to ensure:
- Code reviews are required before merging
- Status checks pass before merging
- Only authorized users can push to the branch

## Usage

### Creating a Stable Release

There are two ways to trigger a stable release:

**Method 1: Push tag to trigger workflow**
1. Ensure all changes are committed on the `master` or `release` branch
2. Create and push a version tag:
```bash
git checkout master # or release
git tag 0.43.0
git push origin 0.43.0
```
Comment thread
adamhathcock marked this conversation as resolved.
3. The workflow will automatically trigger, build, test, and publish `SharpCompress 0.43.0` to NuGet.org (Windows build)

**Method 2: Tag after pushing to branch**
1. Ensure all changes are merged and pushed to the `master` or `release` branch
2. Create and push a version tag on the already-pushed commit:
```bash
git checkout master # or release
git tag 0.43.0
git push origin 0.43.0
```
3. The workflow will automatically trigger, build, test, and publish `SharpCompress 0.43.0` to NuGet.org (Windows build)

### Creating a Prerelease

1. Push changes to the `master` or `release` branch without tagging:
```bash
git checkout master # or release
git push origin master # or release
```
2. The workflow will automatically:
- Build and test the project on both Windows and Ubuntu
- Publish a prerelease version like `0.43.0-beta.456` to NuGet.org (Windows build)

## Troubleshooting

### Workflow Fails to Push to NuGet

- **Check the API Key**: Ensure `NUGET_API_KEY` is set correctly in repository secrets
- **Check API Key Permissions**: Verify the API key has "Push" permission for SharpCompress
- **Check API Key Expiration**: NuGet API keys may expire; create a new one if needed

### Version Conflict

If you see "Package already exists" errors:
- The workflow uses `--skip-duplicate` flag to handle this gracefully
- If you need to republish the same version, delete it from NuGet.org first (if allowed)

### Build or Test Failures

- The workflow will not push to NuGet if build or tests fail
- Check the workflow logs in GitHub Actions for details
- Fix the issues and push again

## Manual Package Creation

If you need to create a package manually without publishing:

```bash
dotnet run --project build/build.csproj -- publish
```

The package will be created in the `artifacts/` directory.

## Build Targets

The workflow uses the following C# build targets defined in `build/Program.cs`:

- **determine-version**: Detects version from git tags and outputs VERSION and PRERELEASE variables
- **update-version**: Updates VersionPrefix, AssemblyVersion, and FileVersion in the project file
- **push-to-nuget**: Pushes the generated NuGet packages to NuGet.org (requires NUGET_API_KEY)

These targets can be run manually for testing:

```bash
# Determine the version
dotnet run --project build/build.csproj -- determine-version

# Update version in project file
VERSION=0.43.0 dotnet run --project build/build.csproj -- update-version

# Push to NuGet (requires NUGET_API_KEY environment variable)
NUGET_API_KEY=your-key dotnet run --project build/build.csproj -- push-to-nuget
```

## Related Files

- `.github/workflows/nuget-release.yml` - The workflow definition
- `build/Program.cs` - Build script with version detection and publishing logic
- `src/SharpCompress/SharpCompress.csproj` - Project file with version information
120 changes: 120 additions & 0 deletions .github/workflows/TESTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
# Testing Guide for NuGet Release Workflow

This document describes how to test the NuGet release workflow.

## Testing Strategy

Since this workflow publishes to NuGet.org and requires repository secrets, testing should be done carefully. The workflow runs on both Windows and Ubuntu, but only the Windows build publishes to NuGet.

## Pre-Testing Checklist

- [x] Workflow YAML syntax validated
- [x] Version determination logic tested locally
- [x] Version update logic tested locally
- [x] Build script works (`dotnet run --project build/build.csproj`)

## Manual Testing Steps

### 1. Test Prerelease Publishing (Recommended First Test)

This tests the workflow on untagged commits to the master or release branch.

**Steps:**
1. Ensure `NUGET_API_KEY` secret is configured in repository settings
2. Create a test commit on the `master` or `release` branch (e.g., update a comment or README)
3. Push to the `master` or `release` branch
4. Monitor the GitHub Actions workflow at: https://github.com/adamhathcock/sharpcompress/actions
5. Verify:
- Workflow triggers and runs successfully on both Windows and Ubuntu
- Version is determined correctly (e.g., `0.43.0-beta.XXX` if last tag is 0.42.x)
- Build and tests pass on both platforms
- Package artifacts are uploaded for both platforms
- Package is pushed to NuGet.org as prerelease (Windows build only)

**Expected Outcome:**
- A new prerelease package appears on NuGet.org: https://www.nuget.org/packages/SharpCompress/
- Package version follows pattern: `{NEXT_MINOR_VERSION}-beta.{COMMIT_COUNT}`

### 2. Test Tagged Release Publishing

This tests the workflow when a version tag is pushed.

**Steps:**
1. Prepare the `master` or `release` branch with all desired changes
2. Create a version tag (must be a pure semantic version like `MAJOR.MINOR.PATCH`):
```bash
git checkout master # or release
git tag 0.42.2
git push origin 0.42.2
Comment thread
adamhathcock marked this conversation as resolved.
```
3. Monitor the GitHub Actions workflow
4. Verify:
- Workflow triggers and runs successfully on both Windows and Ubuntu
- Version is determined as the tag (e.g., `0.42.2`)
- Build and tests pass on both platforms
- Package artifacts are uploaded for both platforms
- Package is pushed to NuGet.org as stable release (Windows build only)

**Expected Outcome:**
- A new stable release package appears on NuGet.org
- Package version matches the tag

### 3. Test Duplicate Package Handling

This tests the `--skip-duplicate` flag behavior.

**Steps:**
1. Push to the `release` branch without making changes
2. Monitor the workflow
3. Verify:
- Workflow runs but NuGet push is skipped with "duplicate" message
- No errors occur

### 4. Test Build Failure Handling

This tests that failed builds don't publish packages.

**Steps:**
1. Introduce a breaking change in a test or code
2. Push to the `release` branch
3. Verify:
- Workflow runs and detects the failure
- Build or test step fails
- NuGet push step is skipped
- No package is published

## Verification

After each test, verify:

1. **GitHub Actions Logs**: Check the workflow logs for any errors or warnings
2. **NuGet.org**: Verify the package appears with correct version and metadata
3. **Artifacts**: Download and inspect the uploaded artifacts

## Rollback/Cleanup

If testing produces unwanted packages:

1. **Prerelease packages**: Can be unlisted on NuGet.org (Settings → Unlist)
2. **Stable packages**: Cannot be deleted, only unlisted (use test versions)
3. **Tags**: Can be deleted with:
```bash
git tag -d 0.42.2
git push origin :refs/tags/0.42.2
```

## Known Limitations

- NuGet.org does not allow re-uploading the same version
- Deleted packages on NuGet.org reserve the version number
- The workflow requires the `NUGET_API_KEY` secret to be set

## Success Criteria

The workflow is considered successful if:

- ✅ Prerelease versions are published correctly with beta suffix
- ✅ Tagged versions are published as stable releases
- ✅ Build and test failures prevent publishing
- ✅ Duplicate packages are handled gracefully
- ✅ Workflow logs are clear and informative
57 changes: 57 additions & 0 deletions .github/workflows/nuget-release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
name: NuGet Release

on:
push:
branches:
- 'master'
- 'release'
tags:
- '[0-9]+.[0-9]+.[0-9]+'

Comment thread
adamhathcock marked this conversation as resolved.
permissions:
contents: read

jobs:
build-and-publish:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [windows-latest, ubuntu-latest]

steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0 # Fetch all history for versioning

- uses: actions/setup-dotnet@v5
with:
dotnet-version: 10.0.x

# Determine version using C# build target
- name: Determine Version
id: version
run: dotnet run --project build/build.csproj -- determine-version
Comment thread
adamhathcock marked this conversation as resolved.

# Update version in project file using C# build target
- name: Update Version in Project
run: dotnet run --project build/build.csproj -- update-version
env:
VERSION: ${{ steps.version.outputs.version }}

# Build and test
- name: Build and Test
run: dotnet run --project build/build.csproj

Comment thread
adamhathcock marked this conversation as resolved.
# Upload artifacts for verification
- name: Upload NuGet Package
uses: actions/upload-artifact@v6
with:
name: ${{ matrix.os }}-nuget-package
path: artifacts/*.nupkg

# Push to NuGet.org using C# build target (Windows only)
- name: Push to NuGet
if: success() && matrix.os == 'windows-latest'
run: dotnet run --project build/build.csproj -- push-to-nuget
env:
NUGET_API_KEY: ${{ secrets.NUGET_API_KEY }}
Comment thread Fixed
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ tests/TestArchives/*/Scratch2
.vs
tools
.idea/
artifacts/

.DS_Store
*.snupkg
Loading