diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9e0f9e2..84a0cf2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -35,6 +35,15 @@ jobs: --logger "trx;LogFileName=test-results.trx" --collect:"XPlat Code Coverage" + - name: Pack + run: > + dotnet pack src/TableauSharp/TableauSharp.csproj + --no-build + -c Release + -p:ContinuousIntegrationBuild=true + -p:PackageVersion=0.0.0-ci.${{ github.run_number }} + -o ./artifacts + - name: Upload test results if: always() uses: actions/upload-artifact@v4 @@ -48,3 +57,9 @@ jobs: with: name: coverage path: '**/TestResults/**/coverage.cobertura.xml' + + - name: Upload packages + uses: actions/upload-artifact@v4 + with: + name: nuget-packages + path: ./artifacts/ diff --git a/.github/workflows/publish-nuget.yml b/.github/workflows/publish-nuget.yml index 6ebb5d3..2c2102e 100644 --- a/.github/workflows/publish-nuget.yml +++ b/.github/workflows/publish-nuget.yml @@ -1,10 +1,20 @@ name: Publish to NuGet -# Triggered by a version tag: git tag v0.1.0 && git push --tags on: push: tags: - - 'v[0-9]+.[0-9]+.[0-9]+*' # v0.1.0, v1.0.0-beta, etc. + - 'v*.*.*' + workflow_dispatch: + inputs: + version: + description: 'Package version, for example 0.1.0-alpha.1' + required: true + type: string + dry_run: + description: 'Build, test, pack, and upload artifacts without pushing to NuGet' + required: true + default: true + type: boolean jobs: publish: @@ -24,8 +34,20 @@ jobs: - name: Extract version from tag id: version - # Strip the leading 'v' from the tag name (v0.1.0 → 0.1.0) - run: echo "VERSION=${GITHUB_REF_NAME#v}" >> "$GITHUB_OUTPUT" + shell: bash + run: | + if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then + VERSION="${{ inputs.version }}" + else + VERSION="${GITHUB_REF_NAME#v}" + fi + + if [[ ! "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+([-.][0-9A-Za-z.-]+)?$ ]]; then + echo "::error::Invalid package version '$VERSION'. Use a SemVer value such as 0.1.0-alpha.1." + exit 1 + fi + + echo "VERSION=$VERSION" >> "$GITHUB_OUTPUT" - name: Restore run: dotnet restore TableauSharp.sln @@ -41,22 +63,36 @@ jobs: dotnet pack src/TableauSharp/TableauSharp.csproj --no-build -c Release + -p:ContinuousIntegrationBuild=true -p:PackageVersion=${{ steps.version.outputs.VERSION }} -o ./artifacts - name: Publish to NuGet - run: > - dotnet nuget push ./artifacts/*.nupkg - --api-key ${{ secrets.NUGET_API_KEY }} - --source https://api.nuget.org/v3/index.json - --skip-duplicate + if: ${{ github.event_name == 'push' || inputs.dry_run == false }} + env: + NUGET_API_KEY: ${{ secrets.NUGET_API_KEY }} + shell: bash + run: | + if [ -z "$NUGET_API_KEY" ]; then + echo "::error::NUGET_API_KEY repository secret is required to publish packages." + exit 1 + fi + + dotnet nuget push ./artifacts/*.nupkg \ + --api-key "$NUGET_API_KEY" \ + --source https://api.nuget.org/v3/index.json \ + --skip-duplicate - name: Publish symbols - run: > - dotnet nuget push ./artifacts/*.snupkg - --api-key ${{ secrets.NUGET_API_KEY }} - --source https://api.nuget.org/v3/index.json - --skip-duplicate + if: ${{ github.event_name == 'push' || inputs.dry_run == false }} + env: + NUGET_API_KEY: ${{ secrets.NUGET_API_KEY }} + shell: bash + run: | + dotnet nuget push ./artifacts/*.snupkg \ + --api-key "$NUGET_API_KEY" \ + --source https://api.nuget.org/v3/index.json \ + --skip-duplicate - name: Upload artifacts uses: actions/upload-artifact@v4 diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..baf9709 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 Teesofttech + +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. diff --git a/README.md b/README.md index 32b2442..7a7ffaa 100644 --- a/README.md +++ b/README.md @@ -19,10 +19,10 @@ ## Installation -Coming soon to NuGet: +Install prerelease packages from NuGet as modules reach preview quality: ```powershell -dotnet add package TableauSharp +dotnet add package TableauSharp --prerelease ``` For now, clone the repository: @@ -31,6 +31,8 @@ For now, clone the repository: git clone https://github.com/teesofttech/TableauSharp.git ``` +Maintainers can publish prerelease packages from GitHub Actions. See [Release Process](docs/release.md). + --- ## Configuration (appsettings.json) diff --git a/docs/release.md b/docs/release.md new file mode 100644 index 0000000..7661e00 --- /dev/null +++ b/docs/release.md @@ -0,0 +1,57 @@ +# Release Process + +TableauSharp publishes prerelease NuGet packages from GitHub Actions. + +## Prerequisites + +- `NUGET_API_KEY` repository secret with permission to push `TableauSharp`. +- Passing CI on `master`. +- A prerelease version, for example `0.1.0-alpha.1`. + +## Validate Locally + +```bash +dotnet restore TableauSharp.sln +dotnet build TableauSharp.sln -c Release --no-restore +dotnet test TableauSharp.sln -c Release --no-build +dotnet pack src/TableauSharp/TableauSharp.csproj -c Release --no-build -p:PackageVersion=0.1.0-alpha.1 -o ./artifacts +``` + +## Dry Run In GitHub Actions + +Run **Publish to NuGet** manually from GitHub Actions: + +- `version`: prerelease version, for example `0.1.0-alpha.1` +- `dry_run`: `true` + +The workflow restores, builds, tests, packs, and uploads package artifacts without pushing to NuGet. + +## Publish A Prerelease + +Run **Publish to NuGet** manually with: + +- `version`: prerelease version, for example `0.1.0-alpha.1` +- `dry_run`: `false` + +The workflow fails before publishing if `NUGET_API_KEY` is missing. + +## Publish From A Tag + +Maintainers can also publish by pushing a version tag: + +```bash +git tag v0.1.0-alpha.1 +git push origin v0.1.0-alpha.1 +``` + +Tags matching `v*.*.*` trigger the publish workflow. The package version is the tag name without the leading `v`. + +## Versioning + +Use prerelease versions until the SDK reaches a stable surface: + +- `0.1.0-alpha.1` +- `0.1.0-alpha.2` +- `0.1.0-beta.1` + +Do not reuse a NuGet package version once it has been published.