# yaml-language-server: $schema=https://json.schemastore.org/github-action.json # permissions: # - packages: write # Required for publishing to GitHub Packages # - contents: read # Required for checking out repository --- name: C# Publish description: 'Publishes a C# project to GitHub Packages.' author: 'Ismo Vuorinen' branding: icon: package color: blue inputs: dotnet-version: description: 'Version of .NET SDK to use.' required: false namespace: description: 'GitHub namespace for the package.' required: true default: 'ivuorinen' token: description: 'GitHub token with package write permissions' required: false outputs: publish_status: description: 'Overall publish status (success/failure)' value: ${{ steps.set-status.outputs.status }} package_version: description: 'Version of the published package' value: ${{ steps.extract-version.outputs.version }} package_url: description: 'URL of the published package' value: ${{ steps.publish-package.outputs.package_url }} runs: using: composite steps: - name: Mask Secrets shell: bash env: API_KEY: ${{ inputs.token || github.token }} run: | echo "::add-mask::$API_KEY" - name: Checkout Repository uses: actions/checkout@71cf2267d89c5cb81562390fa70a37fa40b1305e # v6-beta with: token: ${{ inputs.token || github.token }} - name: Validate Inputs id: validate uses: ivuorinen/actions/validate-inputs@0fa9a68f07a1260b321f814202658a6089a43d42 with: action-type: 'csharp-publish' token: ${{ inputs.token }} namespace: ${{ inputs.namespace }} dotnet-version: ${{ inputs.dotnet-version }} - name: Detect .NET SDK Version id: detect-dotnet-version uses: ivuorinen/actions/language-version-detect@0fa9a68f07a1260b321f814202658a6089a43d42 with: language: 'dotnet' default-version: '7.0' - name: Setup .NET SDK uses: actions/setup-dotnet@d4c94342e560b34958eacfc5d055d21461ed1c5d # v5.0.0 with: dotnet-version: ${{ inputs.dotnet-version || steps.detect-dotnet-version.outputs.detected-version }} - name: Cache NuGet packages id: cache-nuget uses: ivuorinen/actions/common-cache@0fa9a68f07a1260b321f814202658a6089a43d42 with: type: 'nuget' paths: '~/.nuget/packages' key-files: '**/*.csproj,**/*.props,**/*.targets' key-prefix: 'csharp-publish' - name: Restore Dependencies shell: bash env: CACHE_HIT: ${{ steps.cache-nuget.outputs.cache-hit }} run: | set -euo pipefail # Always run dotnet restore to ensure project.assets.json is present if [[ "$CACHE_HIT" == 'true' ]]; then echo "Cache hit - running fast dotnet restore" fi dotnet restore - name: Build Solution shell: bash run: | set -euo pipefail dotnet build --configuration Release --no-restore - name: Pack Solution shell: bash run: | set -euo pipefail dotnet pack --configuration Release --no-build --no-restore --output ./artifacts - name: Extract Package Version id: extract-version shell: bash run: | set -euo pipefail # Find the newest .nupkg file by modification time and extract version PACKAGE_FILE=$(find ./artifacts -name "*.nupkg" -type f -printf '%T@ %p\n' | sort -rn | head -n 1 | cut -d' ' -f2-) if [ -n "$PACKAGE_FILE" ]; then # Extract version from filename (assumes standard naming: PackageName.Version.nupkg) VERSION=$(basename "$PACKAGE_FILE" .nupkg | sed 's/.*\.\([0-9]\+\.[0-9]\+\.[0-9]\+.*\)$/\1/') printf '%s\n' "version=$VERSION" >> "$GITHUB_OUTPUT" printf '%s\n' "package_file=$PACKAGE_FILE" >> "$GITHUB_OUTPUT" else printf '%s\n' "version=unknown" >> "$GITHUB_OUTPUT" printf '%s\n' "package_file=" >> "$GITHUB_OUTPUT" fi - name: Publish Package id: publish-package shell: bash env: API_KEY: ${{ inputs.token || github.token }} NAMESPACE: ${{ inputs.namespace }} run: | set -euo pipefail PACKAGE_URL="https://github.com/$NAMESPACE/packages/nuget" printf '%s\n' "package_url=$PACKAGE_URL" >> "$GITHUB_OUTPUT" # First attempt if ! dotnet nuget push ./artifacts/*.nupkg \ --api-key "$API_KEY" \ --source "https://nuget.pkg.github.com/$NAMESPACE/index.json" \ --skip-duplicate \ --no-symbols; then echo "::warning::First publish attempt failed, retrying after 5 seconds..." sleep 5 dotnet nuget push ./artifacts/*.nupkg \ --api-key "$API_KEY" \ --source "https://nuget.pkg.github.com/$NAMESPACE/index.json" \ --skip-duplicate \ --no-symbols fi - name: Set publish status output if: always() id: set-status shell: bash env: PUBLISH_STATUS: ${{ steps.publish-package.outcome == 'success' && 'success' || 'failure' }} run: |- printf '%s\n' "status=$PUBLISH_STATUS" >> "$GITHUB_OUTPUT"