Open BinToss opened 1 year ago
I can take a look at this, but it probably needs more refinement. The reason publishToGitLab
exists is, that the handling is a bit different there. I am not sure about GitHubs registry, but I guess it is similar using some special CI variables. We either must resolve env vars in the server url, or add some type property to it
{
"registries": [
{
"url": "https://nuget.mycomapny.com/v3/index.json",
"token": "${PRIVATE_TOKEN}"
},
{
"url": "https://npr.customserver.com/v3/index.json",
"token": "${OTHER_TOKEN}"
},
{
"url": "${CI_SERVER_URL}/api/v4/projects/{CI_PROJECT_ID}/packages/nuget/index.json",
"token": "${CI_JOB_TOKEN}",
"type": "gitlab"
}
]
}
Currently, my release
workflow is as follows:
# Test changes locally with https://github.com/nektos/act
# Design with graphs via https://marketplace.visualstudio.com/items?itemName=actionforge.actionforge
name: Release
on:
push:
branches:
- main
- develop
env:
DOTNET_ROLL_FORWARD: "Major"
DOTNET_CLI_TELEMETRY_OPTOUT: 1
DOTNET_SKIP_FIRST_TIME_EXPERIENCE: 1
DOTNET_NOLOGO: 1
jobs:
ci:
name: CI
uses: ./.github/workflows/ci.yml
# based on https://github.com/semantic-release/semantic-release/blob/master/docs/recipes/ci-configurations/github-actions.md
release:
needs: [ci]
runs-on: ubuntu-latest
permissions:
contents: write # to be able to publish a GitHub release
issues: write # to be able to comment on released issues
pull-requests: write # to be able to comment on released pull requests
id-token: write # to enable use of OIDC for npm provenance
packages: write # for pushing GitHub Nuget packages
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # necessary for semantic release
- uses: actions/setup-node@v4
with:
cache: "npm"
check-latest: true
node-version-file: package.json
- run: npm i -g npm@latest # required for attestation. There's a games-stopping bug in Node.js LTS's NPM.
- uses: actions/setup-dotnet@v4
with:
dotnet-version: "8.x"
- name: NPM - Clean Install
run: npm ci
- name: NPM - Audit Signatures
run: npm audit signatures
- name: Update version in README's Avalonia badge
shell: pwsh
run: |
$AV = [version]::new(((dotnet msbuild .\GroupBox.Avalonia\GroupBox.Avalonia.csproj -getItem:PackageReference | ConvertFrom-Json).Items.PackageReference | Where-Object {$_.Identity -eq 'Avalonia'}).Version).ToString();
$pattern = "(?<=\[!\[avalonia]\(https:\/\/img\.shields\.io\/badge\/avalonia-v)\d+\.\d+\.\d+";
(Get-Content -Path README.md -Raw) -creplace $pattern, $AV | Set-Content -NoNewLine -Path README.md
# [release#
# steps](https://github.com/semantic-release/semantic-release#release-steps)
# Plugins add sub-steps e.g. @semantic-release/git's Prepare will create a
# release commit, including configurable file assets."
# After the new version Git tagged, @semantic-release/exec runs
# `dotnet publish`. @semantic-release/github adds the artifacts to the
# GitHub Release.
- name: Semantic Release
id: semantic_release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NUGET_TOKEN: ${{ secrets.NUGET_TOKEN }}
shell: pwsh
run: |
$output=npx semantic-release
if ($output.EndsWith('There are no relevant changes, so no new version is released.')) {
echo "NoNewVersion=true" >> "$env:GITHUB_OUTPUT"
}
# https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-nuget-registry
# https://github.com/actions/setup-dotnet/tree/v3/#setting-up-authentication-for-nuget-feeds
- name: .NET - Pack n' Push NuPkg
if: ${{!steps.semantic_release.outputs.NO_NEW_VERSION}}
env:
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
NUGET_TOKEN: ${{secrets.NUGET_TOKEN}}
shell: pwsh
run: |
dotnet pack ./GroupBox.Avalonia/GroupBox.Avalonia.csproj -o ./publish/
dotnet nuget push ./publish/*.nupkg --source https://api.nuget.org/v3/index.json --api-key $env:NUGET_TOKEN
dotnet nuget push ./publish/*.nupkg --source https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json --api-key $env:GITHUB_TOKEN
packages: write
permission is required for pushing package to GPR! --source
value is notable for the github.repository
variable. This value is also available via the GITHUB_REPOSITORY_OWNER
environment variable.*Some users use a Personal Access Token instead of the workflow's auto-token for edge-cases. They may need a reminder (README?) to update its permissions if they want to push NuGet packages to GitHub.
edit: the url
of a workflow's GitHub Package Repository should default to...
if (process.env["GITHUB_REPOSITORY_OWNER"]) {
const GithubPkgUrl= `https://nuget.pkg.github.com/${process.env["GITHUB_REPOSITORY_OWNER"]}/index.json`
}
or, using the syntax in your example config...
{
"url": "https://nuget.pkg.github.com/${GITHUB_REPOSITORY_OWNER}/index.json",
"token": "${GITHUB_TOKEN}"
}
Regarding tokens, how would users go about assigning them to each registry via environment variables?
CLI may need to be adjusted, too. Perhaps --registries
with a comma-separated, A-B array (url,key,url,key)?
Your example contains strings such as ${CI_JOB_TOKEN}
. Do you intend this to be a string from which the environment variable is derived?
For example, given "token": "${GITHUB_TOKEN}"
...
// assuming registries is mapped or forEach'ed...hmm...which registry NUGET_TOKEN apply to? If length is one, it's easy.
if (pluginConfig.registries[i].token && pluginConfig.registries[i].token.startsWith("${") {
token = process.env[pluginConfig.registries[i].token.replace("${").replace("}")];
}
Regarding tokens, how would users go about assigning them to each registry via environment variables?
The idea was, to specify credentials along with the NuGet source but instead of hardcoding them (which would be bad practice) allow to use environment variables that the plugin can resolve.
Your example contains strings such as ${CI_JOB_TOKEN}. Do you intend this to be a string from which the environment variable is derived?
${CI_JOB_TOKEN}
would be resolved in the verify step and replaced with the content of that environment variable. In GitLab CI this is a variable filled by GitLab with a token with enough rights to be used for that specific case.
In your case it would look more like this
"registries": [
{
"name": "default",
// url could be omitted for official NuGet server
"token": "${NUGET_TOKEN}"
},
{
"name": "github-public",
"url": "https://nuget.pkg.github.com/${GITHUB_REPOSITORY_OWNER}/index.json",
"token": "${GITHUB_TOKEN}",
"type": "github"
}
]
Maybe it would be better to build the url automatically instead of allowing to use env vars in it by using the type?. Type could be something like
default
(NuGet.org)gitlab_private
(needs host, group, repo)gitlab_public
(needs group and repo names)github
(needs orga or user of the repo)custom_nuget_server
(this needs an url to be set)
This will require semantic-release-nuget's configuration object to be changed.
Currently, semantic-release-nuget only allows pushing to one custom server with
NUGET_TOKEN
. This prevents users from pushing to multiple servers e.g. NuGet.org and GitHub registries. This could be alleviated by a GitHub equivalent topublishToGitLab
, but the problem still exists when an organization wants to publish their NuPkg(s) to both NuGet.org and a custom, private registry.To allow users to push packages to multiple servers, server URLs and API tokens will need to be passed as an array of pairs i.e.
Alternatively, an array of well-defined objects which could help with hints/suggestions in IDEs when semantic-release improves support for plugins' parameters.