diff --git a/.github/workflows/build-macos.yml b/.github/workflows/build-macos.yml deleted file mode 100644 index bef1750..0000000 --- a/.github/workflows/build-macos.yml +++ /dev/null @@ -1,55 +0,0 @@ -name: build-macos - -on: - push: - paths-ignore: - - "**.md" - - LICENSE - branches: - - "master" - pull_request: - paths-ignore: - - "**.md" - - LICENSE - branches: - - master - -jobs: - build-and-test: - runs-on: macos-latest - - steps: - - name: Checkout - uses: actions/checkout@v2 - - - name: Init - run: chmod +x ./build.sh - - - name: Install NuGet - uses: NuGet/setup-nuget@v1.0.5 - - - name: Setup Testspace - uses: testspace-com/setup-testspace@v1 - with: - domain: ${{github.repository_owner}} - - - name: Install .NET 8 - uses: actions/setup-dotnet@v1 - with: - dotnet-version: "8.0.x" - - - name: Install .NET 9 - uses: actions/setup-dotnet@v1 - with: - dotnet-version: "9.0.x" - - - name: Build - run: ./build.sh --target build - - - name: Run Tests - run: ./build.sh --target tests --exclusive - - - name: Push result to Testspace server - run: | - testspace [macos]**/*.trx - if: always() \ No newline at end of file diff --git a/.github/workflows/build-ubuntu.yml b/.github/workflows/build-ubuntu.yml deleted file mode 100644 index f82fb3e..0000000 --- a/.github/workflows/build-ubuntu.yml +++ /dev/null @@ -1,55 +0,0 @@ -name: build-ubuntu - -on: - push: - paths-ignore: - - "**.md" - - LICENSE - branches: - - "master" - pull_request: - paths-ignore: - - "**.md" - - LICENSE - branches: - - master - -jobs: - build-and-test: - runs-on: ubuntu-20.04 - - steps: - - name: Checkout - uses: actions/checkout@v2 - - - name: Init - run: chmod +x ./build.sh - - - name: Install NuGet - uses: NuGet/setup-nuget@v1.0.5 - - - name: Setup Testspace - uses: testspace-com/setup-testspace@v1 - with: - domain: ${{github.repository_owner}} - - - name: Install .NET 8 - uses: actions/setup-dotnet@v1 - with: - dotnet-version: "8.0.x" - - - name: Install .NET 9 - uses: actions/setup-dotnet@v1 - with: - dotnet-version: "9.0.x" - - - name: Build - run: ./build.sh --target build - - - name: Run Tests - run: ./build.sh --target tests --skipFunctionalTest false --exclusive - - - name: Push result to Testspace server - run: | - testspace [linux]**/*.trx - if: always() \ No newline at end of file diff --git a/.github/workflows/build-windows.yml b/.github/workflows/build-windows.yml deleted file mode 100644 index f41f8a9..0000000 --- a/.github/workflows/build-windows.yml +++ /dev/null @@ -1,49 +0,0 @@ -name: build-windows - -on: - push: - paths-ignore: - - "**.md" - - LICENSE - branches: - - "master" - pull_request: - paths-ignore: - - "**.md" - - LICENSE - branches: - - master - -jobs: - build-and-test: - runs-on: windows-latest - - steps: - - name: Checkout - uses: actions/checkout@v2 - - - name: Setup Testspace - uses: testspace-com/setup-testspace@v1 - with: - domain: ${{github.repository_owner}} - - - name: Install .NET 8 - uses: actions/setup-dotnet@v1 - with: - dotnet-version: "8.0.x" - - - name: Install .NET 9 - uses: actions/setup-dotnet@v1 - with: - dotnet-version: "9.0.x" - - - name: Build - run: .\build.ps1 --target build - - - name: Run Tests - run: .\build.ps1 --target tests --exclusive - - - name: Push result to Testspace server - run: | - testspace [windows]**/*.trx - if: always() \ No newline at end of file diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..a494c1a --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,95 @@ +name: "CI/CD Pipeline" + +on: + push: + paths-ignore: + - "**.md" + - LICENSE + branches: + - "master" + pull_request: + paths-ignore: + - "**.md" + - LICENSE + branches: + - master + - "feature/*" + +env: + DOTNET_CLI_TELEMETRY_OPTOUT: true + DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true + DOTNET_NOLOGO: true + +jobs: + build-and-test: + name: "Build & Test (${{ matrix.name }})" + runs-on: ${{ matrix.os }} + env: + NUGET_PACKAGES: ${{ contains(matrix.os, 'windows') && format('{0}\.nuget\packages', github.workspace) || format('{0}/.nuget/packages', github.workspace) }} + + strategy: + fail-fast: false + matrix: + include: + - os: windows-latest + name: "Windows" + script: "./build.ps1" + + - os: ubuntu-22.04 + name: "Linux" + script: "./build.sh" + + - os: macos-latest + name: "macOS" + script: "./build.sh" + + steps: + - name: "Checkout" + uses: actions/checkout@v4 + with: + fetch-depth: 0 # Full history for better caching + + - name: "Setup .NET SDK" + uses: actions/setup-dotnet@v4 + with: + dotnet-version: | + 8.0.x + 9.0.x + + - name: "Make build script executable" + if: runner.os != 'Windows' + run: chmod +x ./build.sh + + - name: "Cache NuGet packages" + uses: actions/cache@v4 + with: + path: ${{ runner.os == 'Windows' && format('{0}\.nuget\packages', github.workspace) || format('{0}/.nuget/packages', github.workspace) }} + key: ${{ runner.os }}-nuget-${{ hashFiles('**/packages.lock.json', '**/*.csproj', '**/Directory.Packages.props') }} + restore-keys: | + ${{ runner.os }}-nuget- + + - name: "Build" + run: ${{ matrix.script }} --target build + + - name: "Run Tests" + run: ${{ matrix.script }} --target tests --skipFunctionalTest ${{ runner.os == 'Linux' && 'false' || 'true' }} --exclusive + + - name: "Publish Test Results" + uses: dorny/test-reporter@v1 + if: success() || failure() + with: + name: 'Test Results (${{ matrix.name }})' + path: '**/TestResults/*.trx' + reporter: 'dotnet-trx' + fail-on-error: true + max-annotations: 50 + + - name: "Upload Test Artifacts" + uses: actions/upload-artifact@v4 + if: failure() + with: + name: test-results-${{ matrix.name }} + path: | + **/*.trx + **/TestResults/**/* + retention-days: 7 diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml new file mode 100644 index 0000000..2f7ccaf --- /dev/null +++ b/.github/workflows/dependency-review.yml @@ -0,0 +1,27 @@ +name: Dependency Review + +on: + pull_request: + branches: + - master + - "feature/*" + +permissions: + contents: read + pull-requests: write + +jobs: + dependency-review: + name: "Dependency Review" + runs-on: ubuntu-latest + steps: + - name: "Checkout" + uses: actions/checkout@v4 + + - name: "Dependency Review" + uses: actions/dependency-review-action@v4 + with: + # Fail the check if a vulnerability with 'moderate' severity or higher is found. + fail-on-severity: moderate + # Always post a summary of the check as a comment on the PR. + comment-summary-in-pr: always \ No newline at end of file diff --git a/.github/workflows/publish-dev-github.yml b/.github/workflows/publish-dev-github.yml new file mode 100644 index 0000000..f9d8d27 --- /dev/null +++ b/.github/workflows/publish-dev-github.yml @@ -0,0 +1,166 @@ +name: "Auto Publish to GitHub Packages" + +on: + push: + branches: + - master + paths-ignore: + - "**.md" + - LICENSE + - ".github/**" + - "docs/**" + +env: + DOTNET_CLI_TELEMETRY_OPTOUT: true + DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true + DOTNET_NOLOGO: true + +jobs: + auto-publish: + name: "Auto Publish Development Build" + runs-on: ubuntu-22.04 + if: github.repository == 'localstack-dotnet/localstack-dotnet-client' + env: + NUGET_PACKAGES: ${{ github.workspace }}/.nuget/packages + + permissions: + contents: read + packages: write + + steps: + - name: "Checkout" + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: "Setup .NET SDK" + uses: actions/setup-dotnet@v4 + with: + dotnet-version: | + 8.0.x + 9.0.x + + - name: "Cache NuGet packages" + uses: actions/cache@v4 + with: + path: ${{ github.workspace }}/.nuget/packages + key: ${{ runner.os }}-nuget-${{ hashFiles('**/packages.lock.json', '**/*.csproj', '**/Directory.Packages.props') }} + restore-keys: | + ${{ runner.os }}-nuget- + + - name: "Make build script executable" + run: chmod +x ./build.sh + + - name: "Build & Test" + run: ./build.sh --target tests --skipFunctionalTest true + + - name: "Generate Development Version" + id: version + run: | + # Extract base version from Directory.Build.props + BASE_VERSION=$(grep -oP '\K[^<]+' Directory.Build.props) + + # Generate build metadata + BUILD_DATE=$(date +%Y%m%d) + COMMIT_SHA=$(git rev-parse --short HEAD) + BRANCH_NAME=$(echo "${{ github.ref_name }}" | sed 's/[^a-zA-Z0-9-]/-/g') + + # Version format: 2.0.0-preview1.20240715.a1b2c3d + if [[ "${{ github.ref_name }}" == "master" ]]; then + DEV_VERSION="${BASE_VERSION}.${BUILD_DATE}.${COMMIT_SHA}" + else + DEV_VERSION="${BASE_VERSION}-${BRANCH_NAME}.${BUILD_DATE}.${COMMIT_SHA}" + fi + + echo "base-version=${BASE_VERSION}" >> $GITHUB_OUTPUT + echo "dev-version=${DEV_VERSION}" >> $GITHUB_OUTPUT + echo "build-date=${BUILD_DATE}" >> $GITHUB_OUTPUT + echo "commit-sha=${COMMIT_SHA}" >> $GITHUB_OUTPUT + + echo "📦 Generated development version: ${DEV_VERSION}" + + - name: "Setup GitHub Packages Authentication" + run: | + dotnet nuget add source https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json \ + --name github-packages \ + --username ${{ github.actor }} \ + --password ${{ secrets.GITHUB_TOKEN }} \ + --store-password-in-clear-text + + - name: "Pack & Publish LocalStack.Client" + run: | + echo "🔨 Building LocalStack.Client package..." + ./build.sh --target nuget-pack \ + --package-source github \ + --package-id LocalStack.Client \ + --package-version ${{ steps.version.outputs.dev-version }} + + echo "📤 Publishing LocalStack.Client to GitHub Packages..." + ./build.sh --target nuget-push \ + --package-source github \ + --package-id LocalStack.Client \ + --package-version ${{ steps.version.outputs.dev-version }} \ + --package-secret ${{ secrets.GITHUB_TOKEN }} + + - name: "Update Extensions Dependencies" + run: | + echo "🔄 Updating LocalStack.Client.Extensions dependencies..." + cd src/LocalStack.Client.Extensions/ + + # Remove project reference and add package reference + dotnet remove reference ../LocalStack.Client/LocalStack.Client.csproj + dotnet add package LocalStack.Client \ + --version ${{ steps.version.outputs.dev-version }} \ + --source github-packages + + - name: "Pack & Publish LocalStack.Client.Extensions" + run: | + echo "🔨 Building LocalStack.Client.Extensions package..." + ./build.sh --target nuget-pack \ + --package-source github \ + --package-id LocalStack.Client.Extensions \ + --package-version ${{ steps.version.outputs.dev-version }} + + echo "📤 Publishing LocalStack.Client.Extensions to GitHub Packages..." + ./build.sh --target nuget-push \ + --package-source github \ + --package-id LocalStack.Client.Extensions \ + --package-version ${{ steps.version.outputs.dev-version }} \ + --package-secret ${{ secrets.GITHUB_TOKEN }} + + - name: "Upload Package Artifacts" + uses: actions/upload-artifact@v4 + with: + name: "dev-packages-${{ steps.version.outputs.dev-version }}" + path: | + artifacts/*.nupkg + artifacts/*.snupkg + retention-days: 7 + + - name: "Generate Summary" + run: | + echo "## 📦 Development Packages Published" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "| Package | Version | Source |" >> $GITHUB_STEP_SUMMARY + echo "|---------|---------|---------|" >> $GITHUB_STEP_SUMMARY + echo "| LocalStack.Client | \`${{ steps.version.outputs.dev-version }}\` | GitHub Packages |" >> $GITHUB_STEP_SUMMARY + echo "| LocalStack.Client.Extensions | \`${{ steps.version.outputs.dev-version }}\` | GitHub Packages |" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "### 🚀 Installation Instructions" >> $GITHUB_STEP_SUMMARY + echo '```bash' >> $GITHUB_STEP_SUMMARY + echo "# Add GitHub Packages source" >> $GITHUB_STEP_SUMMARY + echo "dotnet nuget add source https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json \\" >> $GITHUB_STEP_SUMMARY + echo " --name github-localstack \\" >> $GITHUB_STEP_SUMMARY + echo " --username USERNAME \\" >> $GITHUB_STEP_SUMMARY + echo " --password GITHUB_TOKEN" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "# Install development packages" >> $GITHUB_STEP_SUMMARY + echo "dotnet add package LocalStack.Client --version ${{ steps.version.outputs.dev-version }} --source github-localstack" >> $GITHUB_STEP_SUMMARY + echo "dotnet add package LocalStack.Client.Extensions --version ${{ steps.version.outputs.dev-version }} --source github-localstack" >> $GITHUB_STEP_SUMMARY + echo '```' >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "### 📊 Build Information" >> $GITHUB_STEP_SUMMARY + echo "- **Base Version**: ${{ steps.version.outputs.base-version }}" >> $GITHUB_STEP_SUMMARY + echo "- **Build Date**: ${{ steps.version.outputs.build-date }}" >> $GITHUB_STEP_SUMMARY + echo "- **Commit**: ${{ steps.version.outputs.commit-sha }}" >> $GITHUB_STEP_SUMMARY + echo "- **Branch**: ${{ github.ref_name }}" >> $GITHUB_STEP_SUMMARY diff --git a/.github/workflows/publish-nuget.yml b/.github/workflows/publish-nuget.yml index 17d60ba..afb009e 100644 --- a/.github/workflows/publish-nuget.yml +++ b/.github/workflows/publish-nuget.yml @@ -1,4 +1,4 @@ -name: "publish-nuget" +name: "Manual Package Publishing" on: workflow_dispatch: @@ -10,10 +10,10 @@ on: type: choice description: Package Source required: true - default: "myget" + default: "nuget" options: - - myget - nuget + - github package-id: type: choice description: Package Id @@ -23,48 +23,111 @@ on: - LocalStack.Client - LocalStack.Client.Extensions +env: + DOTNET_CLI_TELEMETRY_OPTOUT: true + DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true + DOTNET_NOLOGO: true + jobs: - publish-nuget: - runs-on: ubuntu-20.04 + publish-manual: + name: "Publish to ${{ github.event.inputs.package-source }}" + runs-on: ubuntu-22.04 + env: + NUGET_PACKAGES: ${{ github.workspace }}/.nuget/packages + + permissions: + contents: read + packages: write steps: - - name: Checkout - uses: actions/checkout@v2 - - - name: Init - run: chmod +x ./build.sh - - - name: Install NuGet - uses: NuGet/setup-nuget@v1.0.5 + - name: "Checkout" + uses: actions/checkout@v4 - - name: Install .NET 8 - uses: actions/setup-dotnet@v1 + - name: "Setup .NET SDK" + uses: actions/setup-dotnet@v4 with: - dotnet-version: "8.0.x" + dotnet-version: | + 8.0.x + 9.0.x - - name: Install .NET 9 - uses: actions/setup-dotnet@v1 + - name: "Cache NuGet packages" + uses: actions/cache@v4 with: - dotnet-version: "9.0.x" + path: ~/.nuget/packages + key: ${{ runner.os }}-nuget-${{ hashFiles('**/packages.lock.json', '**/*.csproj', '**/Directory.Packages.props') }} + restore-keys: | + ${{ runner.os }}-nuget- + + - name: "Make build script executable" + run: chmod +x ./build.sh + + - name: "Build & Test" + run: ./build.sh --target tests --skipFunctionalTest true - - name: Build & Test - run: ./build.sh + - name: "Print Package Information" + run: | + echo "📦 Package: ${{ github.event.inputs.package-id }}" + echo "🏷️ Version: ${{ github.event.inputs.package-version }}" + echo "🎯 Target: ${{ github.event.inputs.package-source }}" + echo "🔗 Repository: ${{ github.repository }}" - - name: "Print Version" + - name: "Setup GitHub Packages Authentication" + if: ${{ github.event.inputs.package-source == 'github' }} run: | - echo "Package Version: ${{ github.event.inputs.package-version }}" + dotnet nuget add source https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json \ + --name github-packages \ + --username ${{ github.actor }} \ + --password ${{ secrets.GITHUB_TOKEN }} \ + --store-password-in-clear-text - - name: Remove Project Ref & Add latest pack + - name: "Remove Project Reference & Add Package Reference" if: ${{ github.event.inputs.package-id == 'LocalStack.Client.Extensions' }} - run: cd src/LocalStack.Client.Extensions/ && dotnet remove reference ../LocalStack.Client/LocalStack.Client.csproj && dotnet add package LocalStack.Client + run: | + cd src/LocalStack.Client.Extensions/ + + # Remove project reference + dotnet remove reference ../LocalStack.Client/LocalStack.Client.csproj + + # Add package reference based on target source + if [ "${{ github.event.inputs.package-source }}" == "github" ]; then + dotnet add package LocalStack.Client \ + --version ${{ github.event.inputs.package-version }} \ + --source github-packages + else + dotnet add package LocalStack.Client \ + --version ${{ github.event.inputs.package-version }} + fi - - name: Nuget Pack - run: ./build.sh --target nuget-pack --package-source ${{ github.event.inputs.package-source }} --package-id ${{ github.event.inputs.package-id }} --package-version ${{ github.event.inputs.package-version }} + - name: "Pack NuGet Package" + run: | + ./build.sh --target nuget-pack \ + --package-source ${{ github.event.inputs.package-source }} \ + --package-id ${{ github.event.inputs.package-id }} \ + --package-version ${{ github.event.inputs.package-version }} - - name: MyGet Push - if: ${{ github.event.inputs.package-source == 'myget' }} - run: ./build.sh --target nuget-push --package-source ${{ github.event.inputs.package-source }} --package-id ${{ github.event.inputs.package-id }} --package-version ${{ github.event.inputs.package-version }} --package-secret ${{secrets.MYGET_API_KEY}} + - name: "Publish to GitHub Packages" + if: ${{ github.event.inputs.package-source == 'github' }} + run: | + ./build.sh --target nuget-push \ + --package-source github \ + --package-id ${{ github.event.inputs.package-id }} \ + --package-version ${{ github.event.inputs.package-version }} \ + --package-secret ${{ secrets.GITHUB_TOKEN }} - - name: NuGet Push + - name: "Publish to NuGet.org" if: ${{ github.event.inputs.package-source == 'nuget' }} - run: ./build.sh --target nuget-push --package-source ${{ github.event.inputs.package-source }} --package-id ${{ github.event.inputs.package-id }} --package-version ${{ github.event.inputs.package-version }} --package-secret ${{secrets.NUGET_API_KEY}} \ No newline at end of file + run: | + ./build.sh --target nuget-push \ + --package-source nuget \ + --package-id ${{ github.event.inputs.package-id }} \ + --package-version ${{ github.event.inputs.package-version }} \ + --package-secret ${{ secrets.NUGET_API_KEY }} + + - name: "Upload Package Artifacts" + uses: actions/upload-artifact@v4 + with: + name: "packages-${{ github.event.inputs.package-id }}-${{ github.event.inputs.package-version }}" + path: | + artifacts/*.nupkg + artifacts/*.snupkg + retention-days: 30 \ No newline at end of file diff --git a/Directory.Packages.props b/Directory.Packages.props index 432b334..6863198 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -146,8 +146,8 @@ - - + + diff --git a/README.md b/README.md index 95224e5..51c4faa 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# LocalStack .NET Client ![Nuget](https://img.shields.io/nuget/dt/LocalStack.Client) [![NuGet](https://img.shields.io/nuget/v/LocalStack.Client.svg)](https://www.nuget.org/packages/LocalStack.Client/) [![Space Metric](https://localstack-dotnet.testspace.com/spaces/232580/badge?token=bc6aa170f4388c662b791244948f6d2b14f16983)](https://localstack-dotnet.testspace.com/spaces/232580?utm_campaign=metric&utm_medium=referral&utm_source=badge "Test Cases") +# LocalStack .NET Client ![Nuget](https://img.shields.io/nuget/dt/LocalStack.Client) [![NuGet](https://img.shields.io/nuget/v/LocalStack.Client.svg)](https://www.nuget.org/packages/LocalStack.Client/) [![CI/CD Pipeline](https://github.com/localstack-dotnet/localstack-dotnet-client/actions/workflows/ci.yml/badge.svg)](https://github.com/localstack-dotnet/localstack-dotnet-client/actions/workflows/ci.yml) [![Security](https://github.com/localstack-dotnet/localstack-dotnet-client/actions/workflows/security.yml/badge.svg)](https://github.com/localstack-dotnet/localstack-dotnet-client/actions/workflows/security.yml) > ## ⚠️ AWS SDK v4 Transition Notice > @@ -27,16 +27,16 @@ Localstack.NET is an easy-to-use .NET client for [LocalStack](https://github.com | Package | v1.x (AWS SDK v3) | v2.x (AWS SDK v4) - Development | | ---------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| LocalStack.Client | [![NuGet](https://img.shields.io/nuget/v/LocalStack.Client.svg)](https://www.nuget.org/packages/LocalStack.Client/) | [![MyGet](https://img.shields.io/myget/localstack-dotnet-client/v/LocalStack.Client.svg?label=myget)](https://www.myget.org/feed/localstack-dotnet-client/package/nuget/LocalStack.Client) | -| LocalStack.Client.Extensions | [![NuGet](https://img.shields.io/nuget/v/LocalStack.Client.Extensions.svg)](https://www.nuget.org/packages/LocalStack.Client.Extensions/) | [![MyGet](https://img.shields.io/myget/localstack-dotnet-client/v/LocalStack.Client.Extensions.svg?label=myget)](https://www.myget.org/feed/localstack-dotnet-client/package/nuget/LocalStack.Client.Extensions) | +| LocalStack.Client | [![NuGet](https://img.shields.io/nuget/v/LocalStack.Client.svg)](https://www.nuget.org/packages/LocalStack.Client/) | [![GitHub Packages](https://img.shields.io/github/v/release/localstack-dotnet/localstack-dotnet-client?include_prereleases&label=github%20packages)](https://github.com/localstack-dotnet/localstack-dotnet-client/packages) | +| LocalStack.Client.Extensions | [![NuGet](https://img.shields.io/nuget/v/LocalStack.Client.Extensions.svg)](https://www.nuget.org/packages/LocalStack.Client.Extensions/) | [![GitHub Packages](https://img.shields.io/github/v/release/localstack-dotnet/localstack-dotnet-client?include_prereleases&label=github%20packages)](https://github.com/localstack-dotnet/localstack-dotnet-client/packages) | ## Continuous Integration -| Build server | Platform | Build status | -| -------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Github Actions | Ubuntu | [![build-ubuntu](https://github.com/localstack-dotnet/localstack-dotnet-client/actions/workflows/build-ubuntu.yml/badge.svg)](https://github.com/localstack-dotnet/localstack-dotnet-client/actions/workflows/build-ubuntu.yml) | -| Github Actions | Windows | [![build-windows](https://github.com/localstack-dotnet/localstack-dotnet-client/actions/workflows/build-windows.yml/badge.svg)](https://github.com/localstack-dotnet/localstack-dotnet-client/actions/workflows/build-windows.yml) | -| Github Actions | macOS | [![build-macos](https://github.com/localstack-dotnet/localstack-dotnet-client/actions/workflows/build-macos.yml/badge.svg)](https://github.com/localstack-dotnet/localstack-dotnet-client/actions/workflows/build-macos.yml) | +| Build Platform | Status | Description | +|----------------|--------|-------------| +| **Cross-Platform CI** | [![CI/CD Pipeline](https://github.com/localstack-dotnet/localstack-dotnet-client/actions/workflows/ci.yml/badge.svg)](https://github.com/localstack-dotnet/localstack-dotnet-client/actions/workflows/ci.yml) | Matrix testing: Windows, Linux, macOS | +| **Security Analysis** | [![Security](https://github.com/localstack-dotnet/localstack-dotnet-client/actions/workflows/security.yml/badge.svg)](https://github.com/localstack-dotnet/localstack-dotnet-client/actions/workflows/security.yml) | CodeQL analysis & dependency review | +| **Automated Publishing** | [![Auto Publish](https://github.com/localstack-dotnet/localstack-dotnet-client/actions/workflows/publish-dev-github.yml/badge.svg)](https://github.com/localstack-dotnet/localstack-dotnet-client/actions/workflows/publish-dev-github.yml) | Daily GitHub Packages builds | ## Table of Contents @@ -81,13 +81,37 @@ For detailed installation and setup instructions, please refer to the [official ## Getting Started -LocalStack.NET is installed from NuGet. To work with LocalStack in your .NET applications, you'll need the main library and its extensions. Here's how you can install them: +LocalStack.NET is available through multiple package sources to support different development workflows. + +### 📦 Package Installation + +#### Stable Releases (NuGet.org) + +For production use and stable releases: ```bash dotnet add package LocalStack.Client dotnet add package LocalStack.Client.Extensions ``` +#### Development Builds (GitHub Packages) + +For testing latest features and bug fixes: + +```bash +# Add GitHub Packages source +dotnet nuget add source https://nuget.pkg.github.com/localstack-dotnet/index.json \ + --name github-localstack \ + --username YOUR_GITHUB_USERNAME \ + --password YOUR_GITHUB_TOKEN + +# Install development packages +dotnet add package LocalStack.Client --prerelease --source github-localstack +dotnet add package LocalStack.Client.Extensions --prerelease --source github-localstack +``` + +> **🔑 GitHub Packages Authentication**: You'll need a GitHub account and [Personal Access Token](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token) with `read:packages` permission. + Refer to [documentation](https://github.com/localstack-dotnet/localstack-dotnet-client/wiki/Getting-Started#installation) for more information on how to install LocalStack.NET. `LocalStack.NET` is a library that provides a wrapper around the [aws-sdk-net](https://github.com/aws/aws-sdk-net). This means you can use it in a similar way to the `AWS SDK for .NET` and to [AWSSDK.Extensions.NETCore.Setup](https://docs.aws.amazon.com/sdk-for-net/latest/developer-guide/net-dg-config-netcore.html) with a few differences. For more on how to use the AWS SDK for .NET, see [Getting Started with the AWS SDK for .NET](https://docs.aws.amazon.com/sdk-for-net/v3/developer-guide/net-dg-setup.html). diff --git a/build/LocalStack.Build/BuildContext.cs b/build/LocalStack.Build/BuildContext.cs index 4000e4b..7e88440 100644 --- a/build/LocalStack.Build/BuildContext.cs +++ b/build/LocalStack.Build/BuildContext.cs @@ -19,7 +19,8 @@ public BuildContext(ICakeContext context) : base(context) sourceBuilder.AddRange(new[] { new KeyValuePair("myget", "https://www.myget.org/F/localstack-dotnet-client/api/v3/index.json"), - new KeyValuePair("nuget", "https://api.nuget.org/v3/index.json") + new KeyValuePair("nuget", "https://api.nuget.org/v3/index.json"), + new KeyValuePair("github", "https://nuget.pkg.github.com/localstack-dotnet/index.json"), }); PackageSourceMap = sourceBuilder.ToImmutable(); @@ -38,7 +39,7 @@ public BuildContext(ICakeContext context) : base(context) packIdBuilder.AddRange(new[] { new KeyValuePair("LocalStack.Client", LocalStackClientProjFile), - new KeyValuePair("LocalStack.Client.Extensions", LocalStackClientExtProjFile) + new KeyValuePair("LocalStack.Client.Extensions", LocalStackClientExtProjFile), }); PackageIdProjMap = packIdBuilder.ToImmutable(); } @@ -100,7 +101,7 @@ public void InstallXUnitNugetPackage() var nugetInstallSettings = new NuGetInstallSettings { - Version = "2.8.1", Verbosity = NuGetVerbosity.Normal, OutputDirectory = "testrunner", WorkingDirectory = "." + Version = "2.8.1", Verbosity = NuGetVerbosity.Normal, OutputDirectory = "testrunner", WorkingDirectory = ".", }; this.NuGetInstall("xunit.runner.console", nugetInstallSettings); @@ -130,6 +131,69 @@ public IEnumerable GetProjMetadata() return projMetadata; } + public void InstallMonoOnLinux() + { + int result = this.StartProcess("mono", new ProcessSettings + { + Arguments = "--version", + RedirectStandardOutput = true, + NoWorkingDirectory = true, + }); + + if (result == 0) + { + this.Information("✅ Mono is already installed. Skipping installation."); + return; + } + + this.Information("Mono not found. Starting installation on Linux for .NET Framework test platform support..."); + + // Add Mono repository key + int exitCode1 = this.StartProcess("sudo", new ProcessSettings + { + Arguments = "apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF", + }); + + if (exitCode1 != 0) + { + this.Warning($"⚠️ Failed to add Mono repository key (exit code: {exitCode1})"); + return; + } + + // Add Mono repository + int exitCode2 = this.StartProcess("bash", new ProcessSettings + { + Arguments = "-c \"echo 'deb https://download.mono-project.com/repo/ubuntu focal main' | sudo tee /etc/apt/sources.list.d/mono-official-stable.list\"", + }); + + if (exitCode2 != 0) + { + this.Warning($"⚠️ Failed to add Mono repository (exit code: {exitCode2})"); + return; + } + + // Update package list + int exitCode3 = this.StartProcess("sudo", new ProcessSettings { Arguments = "apt update" }); + + if (exitCode3 != 0) + { + this.Warning($"⚠️ Failed to update package list (exit code: {exitCode3})"); + return; + } + + // Install Mono + int exitCode4 = this.StartProcess("sudo", new ProcessSettings { Arguments = "apt install -y mono-complete" }); + + if (exitCode4 != 0) + { + this.Warning($"⚠️ Failed to install Mono (exit code: {exitCode4})"); + this.Warning("This may cause .NET Framework tests to fail on Linux"); + return; + } + + this.Information("✅ Mono installation completed successfully"); + } + public void RunXUnitUsingMono(string targetFramework, string assemblyPath) { int exitCode = this.StartProcess( diff --git a/build/LocalStack.Build/Program.cs b/build/LocalStack.Build/Program.cs index 4190e71..1e2f01d 100644 --- a/build/LocalStack.Build/Program.cs +++ b/build/LocalStack.Build/Program.cs @@ -20,10 +20,6 @@ public override void Run(BuildContext context) } context.StartProcess("git", new ProcessSettings { Arguments = "config --global core.autocrlf true" }); - - context.StartProcess("mono", new ProcessSettings { Arguments = "--version" }); - - context.InstallXUnitNugetPackage(); } } @@ -45,7 +41,7 @@ public override void Run(BuildContext context) var settings = new DotNetTestSettings { - NoRestore = !context.ForceRestore, NoBuild = !context.ForceBuild, Configuration = context.BuildConfiguration, Blame = true + NoRestore = !context.ForceRestore, NoBuild = !context.ForceBuild, Configuration = context.BuildConfiguration, Blame = true, }; IEnumerable projMetadata = context.GetProjMetadata(); @@ -92,21 +88,19 @@ public override void Run(BuildContext context) } } - if (context.IsRunningOnLinux() && targetFramework == "net472") - { - context.Warning("Temporarily disabled running net472 tests on Linux because of a problem in mono runtime"); - } - else if (context.IsRunningOnMacOs() && targetFramework == "net472") - { - context.RunXUnitUsingMono(targetFramework, $"{testProj.DirectoryPath}/bin/{context.BuildConfiguration}/{targetFramework}/{testProj.AssemblyName}.dll"); - } - else + // .NET Framework testing on non-Windows platforms + // - Modern .NET includes built-in Mono runtime + // - Test platform still requires external Mono installation on Linux + if (targetFramework == "net472" && !context.IsRunningOnWindows()) { - string testFilePrefix = targetFramework.Replace(".", "-"); - settings.ArgumentCustomization = args => args.Append($" --logger \"trx;LogFileName={testFilePrefix}_{testResults}\""); - context.DotNetTest(testProjectPath, settings); + string platform = context.IsRunningOnLinux() ? "Linux (with external Mono)" : "macOS (built-in Mono)"; + context.Information($"Running .NET Framework tests on {platform}"); } + string testFilePrefix = targetFramework.Replace(".", "-"); + settings.ArgumentCustomization = args => args.Append($" --logger \"trx;LogFileName={testFilePrefix}_{testResults}\""); + context.DotNetTest(testProjectPath, settings); + context.Warning("=============================================================="); } } @@ -129,7 +123,7 @@ public override void Run(BuildContext context) var settings = new DotNetPackSettings { - Configuration = context.BuildConfiguration, OutputDirectory = context.ArtifactOutput, MSBuildSettings = new DotNetMSBuildSettings() + Configuration = context.BuildConfiguration, OutputDirectory = context.ArtifactOutput, MSBuildSettings = new DotNetMSBuildSettings(), }; settings.MSBuildSettings.SetVersion(context.PackageVersion); @@ -143,13 +137,20 @@ private static void ValidatePackageVersion(BuildContext context) BuildContext.ValidateArgument("package-version", context.PackageVersion); BuildContext.ValidateArgument("package-source", context.PackageSource); - Match match = Regex.Match(context.PackageVersion, @"^(\d+)\.(\d+)\.(\d+)(\.(\d+))*$", RegexOptions.IgnoreCase); + Match match = Regex.Match(context.PackageVersion, @"^(\d+)\.(\d+)\.(\d+)([\.\-].*)*$", RegexOptions.IgnoreCase); if (!match.Success) { throw new Exception($"Invalid version: {context.PackageVersion}"); } + // Skip version validation for GitHub Packages - allows overwriting dev builds + if (context.PackageSource == "github") + { + context.Information($"🔄 Skipping version validation for GitHub Packages source"); + return; + } + string packageSource = context.PackageSourceMap[context.PackageSource]; var nuGetListSettings = new NuGetListSettings { AllVersions = false, Source = new List() { packageSource } }; diff --git a/src/LocalStack.Client.Extensions/README.md b/src/LocalStack.Client.Extensions/README.md index 95224e5..51c4faa 100644 --- a/src/LocalStack.Client.Extensions/README.md +++ b/src/LocalStack.Client.Extensions/README.md @@ -1,4 +1,4 @@ -# LocalStack .NET Client ![Nuget](https://img.shields.io/nuget/dt/LocalStack.Client) [![NuGet](https://img.shields.io/nuget/v/LocalStack.Client.svg)](https://www.nuget.org/packages/LocalStack.Client/) [![Space Metric](https://localstack-dotnet.testspace.com/spaces/232580/badge?token=bc6aa170f4388c662b791244948f6d2b14f16983)](https://localstack-dotnet.testspace.com/spaces/232580?utm_campaign=metric&utm_medium=referral&utm_source=badge "Test Cases") +# LocalStack .NET Client ![Nuget](https://img.shields.io/nuget/dt/LocalStack.Client) [![NuGet](https://img.shields.io/nuget/v/LocalStack.Client.svg)](https://www.nuget.org/packages/LocalStack.Client/) [![CI/CD Pipeline](https://github.com/localstack-dotnet/localstack-dotnet-client/actions/workflows/ci.yml/badge.svg)](https://github.com/localstack-dotnet/localstack-dotnet-client/actions/workflows/ci.yml) [![Security](https://github.com/localstack-dotnet/localstack-dotnet-client/actions/workflows/security.yml/badge.svg)](https://github.com/localstack-dotnet/localstack-dotnet-client/actions/workflows/security.yml) > ## ⚠️ AWS SDK v4 Transition Notice > @@ -27,16 +27,16 @@ Localstack.NET is an easy-to-use .NET client for [LocalStack](https://github.com | Package | v1.x (AWS SDK v3) | v2.x (AWS SDK v4) - Development | | ---------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| LocalStack.Client | [![NuGet](https://img.shields.io/nuget/v/LocalStack.Client.svg)](https://www.nuget.org/packages/LocalStack.Client/) | [![MyGet](https://img.shields.io/myget/localstack-dotnet-client/v/LocalStack.Client.svg?label=myget)](https://www.myget.org/feed/localstack-dotnet-client/package/nuget/LocalStack.Client) | -| LocalStack.Client.Extensions | [![NuGet](https://img.shields.io/nuget/v/LocalStack.Client.Extensions.svg)](https://www.nuget.org/packages/LocalStack.Client.Extensions/) | [![MyGet](https://img.shields.io/myget/localstack-dotnet-client/v/LocalStack.Client.Extensions.svg?label=myget)](https://www.myget.org/feed/localstack-dotnet-client/package/nuget/LocalStack.Client.Extensions) | +| LocalStack.Client | [![NuGet](https://img.shields.io/nuget/v/LocalStack.Client.svg)](https://www.nuget.org/packages/LocalStack.Client/) | [![GitHub Packages](https://img.shields.io/github/v/release/localstack-dotnet/localstack-dotnet-client?include_prereleases&label=github%20packages)](https://github.com/localstack-dotnet/localstack-dotnet-client/packages) | +| LocalStack.Client.Extensions | [![NuGet](https://img.shields.io/nuget/v/LocalStack.Client.Extensions.svg)](https://www.nuget.org/packages/LocalStack.Client.Extensions/) | [![GitHub Packages](https://img.shields.io/github/v/release/localstack-dotnet/localstack-dotnet-client?include_prereleases&label=github%20packages)](https://github.com/localstack-dotnet/localstack-dotnet-client/packages) | ## Continuous Integration -| Build server | Platform | Build status | -| -------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Github Actions | Ubuntu | [![build-ubuntu](https://github.com/localstack-dotnet/localstack-dotnet-client/actions/workflows/build-ubuntu.yml/badge.svg)](https://github.com/localstack-dotnet/localstack-dotnet-client/actions/workflows/build-ubuntu.yml) | -| Github Actions | Windows | [![build-windows](https://github.com/localstack-dotnet/localstack-dotnet-client/actions/workflows/build-windows.yml/badge.svg)](https://github.com/localstack-dotnet/localstack-dotnet-client/actions/workflows/build-windows.yml) | -| Github Actions | macOS | [![build-macos](https://github.com/localstack-dotnet/localstack-dotnet-client/actions/workflows/build-macos.yml/badge.svg)](https://github.com/localstack-dotnet/localstack-dotnet-client/actions/workflows/build-macos.yml) | +| Build Platform | Status | Description | +|----------------|--------|-------------| +| **Cross-Platform CI** | [![CI/CD Pipeline](https://github.com/localstack-dotnet/localstack-dotnet-client/actions/workflows/ci.yml/badge.svg)](https://github.com/localstack-dotnet/localstack-dotnet-client/actions/workflows/ci.yml) | Matrix testing: Windows, Linux, macOS | +| **Security Analysis** | [![Security](https://github.com/localstack-dotnet/localstack-dotnet-client/actions/workflows/security.yml/badge.svg)](https://github.com/localstack-dotnet/localstack-dotnet-client/actions/workflows/security.yml) | CodeQL analysis & dependency review | +| **Automated Publishing** | [![Auto Publish](https://github.com/localstack-dotnet/localstack-dotnet-client/actions/workflows/publish-dev-github.yml/badge.svg)](https://github.com/localstack-dotnet/localstack-dotnet-client/actions/workflows/publish-dev-github.yml) | Daily GitHub Packages builds | ## Table of Contents @@ -81,13 +81,37 @@ For detailed installation and setup instructions, please refer to the [official ## Getting Started -LocalStack.NET is installed from NuGet. To work with LocalStack in your .NET applications, you'll need the main library and its extensions. Here's how you can install them: +LocalStack.NET is available through multiple package sources to support different development workflows. + +### 📦 Package Installation + +#### Stable Releases (NuGet.org) + +For production use and stable releases: ```bash dotnet add package LocalStack.Client dotnet add package LocalStack.Client.Extensions ``` +#### Development Builds (GitHub Packages) + +For testing latest features and bug fixes: + +```bash +# Add GitHub Packages source +dotnet nuget add source https://nuget.pkg.github.com/localstack-dotnet/index.json \ + --name github-localstack \ + --username YOUR_GITHUB_USERNAME \ + --password YOUR_GITHUB_TOKEN + +# Install development packages +dotnet add package LocalStack.Client --prerelease --source github-localstack +dotnet add package LocalStack.Client.Extensions --prerelease --source github-localstack +``` + +> **🔑 GitHub Packages Authentication**: You'll need a GitHub account and [Personal Access Token](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token) with `read:packages` permission. + Refer to [documentation](https://github.com/localstack-dotnet/localstack-dotnet-client/wiki/Getting-Started#installation) for more information on how to install LocalStack.NET. `LocalStack.NET` is a library that provides a wrapper around the [aws-sdk-net](https://github.com/aws/aws-sdk-net). This means you can use it in a similar way to the `AWS SDK for .NET` and to [AWSSDK.Extensions.NETCore.Setup](https://docs.aws.amazon.com/sdk-for-net/latest/developer-guide/net-dg-config-netcore.html) with a few differences. For more on how to use the AWS SDK for .NET, see [Getting Started with the AWS SDK for .NET](https://docs.aws.amazon.com/sdk-for-net/v3/developer-guide/net-dg-setup.html). diff --git a/src/LocalStack.Client/README.md b/src/LocalStack.Client/README.md index 95224e5..51c4faa 100644 --- a/src/LocalStack.Client/README.md +++ b/src/LocalStack.Client/README.md @@ -1,4 +1,4 @@ -# LocalStack .NET Client ![Nuget](https://img.shields.io/nuget/dt/LocalStack.Client) [![NuGet](https://img.shields.io/nuget/v/LocalStack.Client.svg)](https://www.nuget.org/packages/LocalStack.Client/) [![Space Metric](https://localstack-dotnet.testspace.com/spaces/232580/badge?token=bc6aa170f4388c662b791244948f6d2b14f16983)](https://localstack-dotnet.testspace.com/spaces/232580?utm_campaign=metric&utm_medium=referral&utm_source=badge "Test Cases") +# LocalStack .NET Client ![Nuget](https://img.shields.io/nuget/dt/LocalStack.Client) [![NuGet](https://img.shields.io/nuget/v/LocalStack.Client.svg)](https://www.nuget.org/packages/LocalStack.Client/) [![CI/CD Pipeline](https://github.com/localstack-dotnet/localstack-dotnet-client/actions/workflows/ci.yml/badge.svg)](https://github.com/localstack-dotnet/localstack-dotnet-client/actions/workflows/ci.yml) [![Security](https://github.com/localstack-dotnet/localstack-dotnet-client/actions/workflows/security.yml/badge.svg)](https://github.com/localstack-dotnet/localstack-dotnet-client/actions/workflows/security.yml) > ## ⚠️ AWS SDK v4 Transition Notice > @@ -27,16 +27,16 @@ Localstack.NET is an easy-to-use .NET client for [LocalStack](https://github.com | Package | v1.x (AWS SDK v3) | v2.x (AWS SDK v4) - Development | | ---------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| LocalStack.Client | [![NuGet](https://img.shields.io/nuget/v/LocalStack.Client.svg)](https://www.nuget.org/packages/LocalStack.Client/) | [![MyGet](https://img.shields.io/myget/localstack-dotnet-client/v/LocalStack.Client.svg?label=myget)](https://www.myget.org/feed/localstack-dotnet-client/package/nuget/LocalStack.Client) | -| LocalStack.Client.Extensions | [![NuGet](https://img.shields.io/nuget/v/LocalStack.Client.Extensions.svg)](https://www.nuget.org/packages/LocalStack.Client.Extensions/) | [![MyGet](https://img.shields.io/myget/localstack-dotnet-client/v/LocalStack.Client.Extensions.svg?label=myget)](https://www.myget.org/feed/localstack-dotnet-client/package/nuget/LocalStack.Client.Extensions) | +| LocalStack.Client | [![NuGet](https://img.shields.io/nuget/v/LocalStack.Client.svg)](https://www.nuget.org/packages/LocalStack.Client/) | [![GitHub Packages](https://img.shields.io/github/v/release/localstack-dotnet/localstack-dotnet-client?include_prereleases&label=github%20packages)](https://github.com/localstack-dotnet/localstack-dotnet-client/packages) | +| LocalStack.Client.Extensions | [![NuGet](https://img.shields.io/nuget/v/LocalStack.Client.Extensions.svg)](https://www.nuget.org/packages/LocalStack.Client.Extensions/) | [![GitHub Packages](https://img.shields.io/github/v/release/localstack-dotnet/localstack-dotnet-client?include_prereleases&label=github%20packages)](https://github.com/localstack-dotnet/localstack-dotnet-client/packages) | ## Continuous Integration -| Build server | Platform | Build status | -| -------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Github Actions | Ubuntu | [![build-ubuntu](https://github.com/localstack-dotnet/localstack-dotnet-client/actions/workflows/build-ubuntu.yml/badge.svg)](https://github.com/localstack-dotnet/localstack-dotnet-client/actions/workflows/build-ubuntu.yml) | -| Github Actions | Windows | [![build-windows](https://github.com/localstack-dotnet/localstack-dotnet-client/actions/workflows/build-windows.yml/badge.svg)](https://github.com/localstack-dotnet/localstack-dotnet-client/actions/workflows/build-windows.yml) | -| Github Actions | macOS | [![build-macos](https://github.com/localstack-dotnet/localstack-dotnet-client/actions/workflows/build-macos.yml/badge.svg)](https://github.com/localstack-dotnet/localstack-dotnet-client/actions/workflows/build-macos.yml) | +| Build Platform | Status | Description | +|----------------|--------|-------------| +| **Cross-Platform CI** | [![CI/CD Pipeline](https://github.com/localstack-dotnet/localstack-dotnet-client/actions/workflows/ci.yml/badge.svg)](https://github.com/localstack-dotnet/localstack-dotnet-client/actions/workflows/ci.yml) | Matrix testing: Windows, Linux, macOS | +| **Security Analysis** | [![Security](https://github.com/localstack-dotnet/localstack-dotnet-client/actions/workflows/security.yml/badge.svg)](https://github.com/localstack-dotnet/localstack-dotnet-client/actions/workflows/security.yml) | CodeQL analysis & dependency review | +| **Automated Publishing** | [![Auto Publish](https://github.com/localstack-dotnet/localstack-dotnet-client/actions/workflows/publish-dev-github.yml/badge.svg)](https://github.com/localstack-dotnet/localstack-dotnet-client/actions/workflows/publish-dev-github.yml) | Daily GitHub Packages builds | ## Table of Contents @@ -81,13 +81,37 @@ For detailed installation and setup instructions, please refer to the [official ## Getting Started -LocalStack.NET is installed from NuGet. To work with LocalStack in your .NET applications, you'll need the main library and its extensions. Here's how you can install them: +LocalStack.NET is available through multiple package sources to support different development workflows. + +### 📦 Package Installation + +#### Stable Releases (NuGet.org) + +For production use and stable releases: ```bash dotnet add package LocalStack.Client dotnet add package LocalStack.Client.Extensions ``` +#### Development Builds (GitHub Packages) + +For testing latest features and bug fixes: + +```bash +# Add GitHub Packages source +dotnet nuget add source https://nuget.pkg.github.com/localstack-dotnet/index.json \ + --name github-localstack \ + --username YOUR_GITHUB_USERNAME \ + --password YOUR_GITHUB_TOKEN + +# Install development packages +dotnet add package LocalStack.Client --prerelease --source github-localstack +dotnet add package LocalStack.Client.Extensions --prerelease --source github-localstack +``` + +> **🔑 GitHub Packages Authentication**: You'll need a GitHub account and [Personal Access Token](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token) with `read:packages` permission. + Refer to [documentation](https://github.com/localstack-dotnet/localstack-dotnet-client/wiki/Getting-Started#installation) for more information on how to install LocalStack.NET. `LocalStack.NET` is a library that provides a wrapper around the [aws-sdk-net](https://github.com/aws/aws-sdk-net). This means you can use it in a similar way to the `AWS SDK for .NET` and to [AWSSDK.Extensions.NETCore.Setup](https://docs.aws.amazon.com/sdk-for-net/latest/developer-guide/net-dg-config-netcore.html) with a few differences. For more on how to use the AWS SDK for .NET, see [Getting Started with the AWS SDK for .NET](https://docs.aws.amazon.com/sdk-for-net/v3/developer-guide/net-dg-setup.html).