Skip to content

Give each package a readme that stands on its own #7

Give each package a readme that stands on its own

Give each package a readme that stands on its own #7

Workflow file for this run

name: Release (NuGet)
# Publishes the YandexMusic, YandexMusic.Ynison, YandexMusic.Quasar and YandexMusic.DependencyInjection
# packages to NuGet.org.
# Trigger by pushing a version tag, e.g.: git tag v0.1.0 && git push origin v0.1.0
# The tag (without the "v" prefix) IS the package version, and the GitHub Release is created here.
#
# Authentication is Trusted Publishing (OIDC): no long-lived API key is stored anywhere. It requires
# a policy on nuget.org for each package id, naming this repository, this workflow file and the
# "nuget" environment, plus the repository variable NUGET_USER.
on:
push:
tags: [ 'v*' ]
concurrency:
group: release-${{ github.ref }}
cancel-in-progress: false
permissions:
contents: write # create the GitHub Release
id-token: write # OIDC token for NuGet Trusted Publishing
jobs:
publish:
name: Pack & push to NuGet
runs-on: ubuntu-latest
environment: nuget # named by the Trusted Publishing policy; can be protected with reviewers
timeout-minutes: 30
steps:
- name: Checkout
uses: actions/checkout@v7
with:
fetch-depth: 0
- name: Setup .NET (8 / 9 / 10)
uses: actions/setup-dotnet@v6
with:
dotnet-version: |
8.0.x
9.0.x
10.0.x
- name: Resolve version from tag
id: version
run: |
VERSION="${GITHUB_REF_NAME#v}"
echo "value=$VERSION" >> "$GITHUB_OUTPUT"
echo "Publishing version $VERSION"
- name: Restore
run: dotnet restore YandexMusic.slnx
- name: Build (Release)
run: dotnet build YandexMusic.slnx -c Release --no-restore -p:Version=${{ steps.version.outputs.value }}
- name: Test
run: dotnet test YandexMusic.slnx -c Release --no-build
# Only IsPackable=true projects produce packages: YandexMusic, YandexMusic.Ynison,
# YandexMusic.Quasar and YandexMusic.DependencyInjection. Every satellite declares a NuGet
# dependency on the core, so they ship together on one version line. Symbol packages (.snupkg)
# are produced alongside via IncludeSymbols; tests and the sample are IsPackable=false.
- name: Pack
run: dotnet pack YandexMusic.slnx -c Release --no-build -p:Version=${{ steps.version.outputs.value }} -o artifacts
# Trusted Publishing: exchange the GitHub OIDC token for a short-lived NuGet API key.
- name: NuGet login (Trusted Publishing)
id: nuget-login
uses: NuGet/login@v1
with:
user: ${{ vars.NUGET_USER }}
- name: Push to NuGet.org
run: >
dotnet nuget push "artifacts/*.nupkg"
--api-key ${{ steps.nuget-login.outputs.NUGET_API_KEY }}
--source https://api.nuget.org/v3/index.json
--skip-duplicate
# Created as a DRAFT on purpose. The install scripts resolve "latest release" and pick the
# ymt-* archive out of it, so a visible release without those archives is a broken install
# command for everyone. The release is undrafted by the finalize job, once the player
# archives are actually attached.
#
# Re-running a failed release must work, so an existing draft is topped up instead of failing.
- name: Create the GitHub Release (draft)
env:
GH_TOKEN: ${{ github.token }}
TAG: ${{ github.ref_name }}
REPO: ${{ github.repository }}
run: |
if gh release view "$TAG" -R "$REPO" >/dev/null 2>&1; then
echo "Release $TAG already exists (re-run) — refreshing its package assets."
gh release upload "$TAG" artifacts/*.nupkg artifacts/*.snupkg -R "$REPO" --clobber
else
gh release create "$TAG" artifacts/*.nupkg artifacts/*.snupkg -R "$REPO" \
--generate-notes --title "$TAG" --draft
fi
# Publishes the sample terminal player as versioned, self-contained single-file CLIs and attaches
# them to the GitHub Release. Two flavours ship: Windows (net*-windows TFM, real NAudio playback)
# built on Windows, and Linux (plain net10.0 TFM, simulated audio) built on Ubuntu. The build is
# not trimmed because the sample uses reflection-based JSON.
player:
name: Publish player (${{ matrix.rid }})
needs: publish
strategy:
fail-fast: false
matrix:
include:
- os: windows-latest
rid: win-x64
tfm: net10.0-windows10.0.19041.0
- os: ubuntu-latest
rid: linux-x64
tfm: net10.0
runs-on: ${{ matrix.os }}
timeout-minutes: 30
permissions:
contents: write
steps:
- name: Checkout
uses: actions/checkout@v7
with:
fetch-depth: 0
- name: Setup .NET 10
uses: actions/setup-dotnet@v6
with:
dotnet-version: 10.0.x
- name: Resolve version from tag
id: version
shell: bash
run: echo "value=${GITHUB_REF_NAME#v}" >> "$GITHUB_OUTPUT"
- name: Publish (${{ matrix.rid }}, self-contained, single file)
run: >
dotnet publish samples/YandexMusicTerminal/YandexMusicTerminal.csproj
-c Release -r ${{ matrix.rid }} --self-contained true
-p:PublishSingleFile=true -p:Version=${{ steps.version.outputs.value }}
-p:PlayerTargetFramework=${{ matrix.tfm }} -o publish/player
# Windows ships a zip; Linux a tar.gz, so the executable bit survives packaging.
- name: Package
id: package
shell: pwsh
run: |
$version = '${{ steps.version.outputs.value }}'.Split('+')[0]
if ('${{ matrix.rid }}' -eq 'win-x64') {
$archive = "ymt-$version-win-x64.zip"
Compress-Archive -Path publish/player/* -DestinationPath $archive
}
else {
$archive = "ymt-$version-linux-x64.tar.gz"
tar -czf $archive -C publish/player .
}
"archive=$archive" >> $env:GITHUB_OUTPUT
- name: Upload workflow artifact
uses: actions/upload-artifact@v7
with:
name: ymt-${{ steps.version.outputs.value }}-${{ matrix.rid }}
path: ${{ steps.package.outputs.archive }}
- name: Attach to the GitHub Release
env:
GH_TOKEN: ${{ github.token }}
run: gh release upload "${{ github.ref_name }}" "${{ steps.package.outputs.archive }}" --clobber
# The release becomes visible only once both player archives are on it, so "latest release" is
# never a state the install scripts cannot work with.
finalize:
name: Publish the release
needs: [ publish, player ]
runs-on: ubuntu-latest
timeout-minutes: 10
permissions:
contents: write
steps:
- name: Undraft the release
env:
GH_TOKEN: ${{ github.token }}
TAG: ${{ github.ref_name }}
REPO: ${{ github.repository }}
run: |
assets=$(gh release view "$TAG" -R "$REPO" --json assets --jq '[.assets[].name] | join(" ")')
echo "Assets on $TAG: $assets"
for expected in win-x64.zip linux-x64.tar.gz; do
case "$assets" in
*"$expected"*) ;;
*) echo "::error::the release is missing a ymt-*-$expected archive; leaving it as a draft" && exit 1 ;;
esac
done
gh release edit "$TAG" -R "$REPO" --draft=false --latest