Standardmäßig ist der Prompt ausgewählt, der zuerst die Quelle prüft. Sie können zu einem direkten Befehl wechseln oder eine lokale Kopie herunterladen.
Quelldateien prüfen
Lesen Sie SKILL.md und alle von SkillsMP angezeigten Begleitdateien, bevor Sie sich für eine Installation entscheiden.
Mit Codex oder Claude installieren Kopieren Sie diesen Prompt, fügen Sie ihn in Codex, Claude oder einen anderen Assistant ein und lassen Sie die Skill-Seite prüfen und installieren.
Ein direkter Befehl überspringt den Prüf-Prompt. Prüfen Sie die Quelle, bevor Sie ihn ausführen.
Unified release CI/CD pipeline for .NET CLI tools: GitHub Actions workflow producing all distribution formats from a
single version tag trigger, build matrix per Runtime Identifier (RID), artifact staging between jobs, GitHub Releases
with SHA-256 checksums, automated Homebrew formula and winget manifest PR creation, and SemVer versioning strategy with
git tags.
Version assumptions: .NET 8.0+ baseline. GitHub Actions workflow syntax v2. Patterns apply to any CI system but
examples use GitHub Actions.
Scope
Tag-triggered GitHub Actions release workflow
Build matrix per Runtime Identifier (RID)
Artifact staging between CI jobs
GitHub Releases with SHA-256 checksums
Automated Homebrew formula and winget manifest PR creation
SemVer versioning with git tags
Out of scope
General CI/CD patterns (branch strategies, matrix testing) -- see [skill:dotnet-gha-patterns] and
[skill:dotnet-ado-patterns]
Native AOT compilation configuration -- see [skill:dotnet-native-aot]
Distribution strategy decisions -- see [skill:dotnet-cli-distribution]
Package format details -- see [skill:dotnet-cli-packaging]
Container image publishing -- see [skill:dotnet-containers]
Cross-references: [skill:dotnet-cli-distribution] for RID matrix and publish strategy, [skill:dotnet-cli-packaging] for
package format authoring, [skill:dotnet-native-aot] for AOT publish configuration, [skill:dotnet-containers] for
container-based distribution.
Versioning Strategy
SemVer + Git Tags
Use Semantic Versioning (SemVer) with git tags as the single source of truth for release versions.
Tag format:v{major}.{minor}.{patch} (e.g., v1.2.3)
# Tag a release
git tag -a v1.2.3 -m "Release v1.2.3"
git push origin v1.2.3
```bash
### Version Flow
```text
git tag v1.2.3
│
▼
GitHub Actions trigger (on push tags: v*)
│
▼
Extract version from tag: GITHUB_REF_NAME → v1.2.3 → 1.2.3
│
▼
Pass to dotnet publish /p:Version=1.2.3
│
▼
Embed in binary (--version output)
│
▼
Stamp in package manifests (Homebrew, winget, Scoop, NuGet)
```text
### Extracting Version from Tag
```yaml
- name: Extract version from tag
id: version
run: echo >>
```text
```bash
git tag -a v1.3.0-rc.1 -m
```text
---
```yaml
name: Release
on:
push:
tags:
-
permissions:
contents: write
defaults:
run:
shell: bash
:
PROJECT: src/MyCli/MyCli.csproj
DOTNET_VERSION:
:
build:
strategy:
matrix:
include:
- rid: linux-x64
os: ubuntu-latest
- rid: linux-arm64
os: ubuntu-latest
- rid: osx-arm64
os: macos-latest
- rid: win-x64
os: windows-latest
runs-on: }
steps:
- uses: actions/checkout@v4
- uses: actions/setup-dotnet@v4
with:
dotnet-version: }
- name: Extract version
: version
shell: bash
run: >>
- name: Publish
run: >-
dotnet publish } -c Release -r } -o ./publish /p:Version=}
- name: Package (Unix)
: runner.os !=
run: |
-euo pipefail
publish
tar -czf .
- name: Package (Windows)
: runner.os ==
shell: pwsh
run: |
Compress-Archive -Path `
-DestinationPath
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: release-}
path: |
*.tar.gz
*.zip
release:
needs: build
runs-on: ubuntu-latest
steps:
- name: Extract version
: version
run: >>
- name: Download all artifacts
uses: actions/download-artifact@v4
with:
path: artifacts
merge-multiple:
- name: Generate checksums
working-directory: artifacts
run: |
-euo pipefail
shasum -a 256 *.tar.gz *.zip > checksums-sha256.txt
checksums-sha256.txt
- name: Detect pre-release
: prerelease
run: |
-euo pipefail
[[ == *-* ]];
>>
>>
- name: Create GitHub Release
uses: softprops/action-gh-release@v2
with:
name: v}
prerelease: }
generate_release_notes:
files: |
artifacts/*.tar.gz
artifacts/*.zip
artifacts/checksums-sha256.txt
publish-nuget:
needs: release
: }
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-dotnet@v4
with:
dotnet-version: }
- name: Extract version
: version
run: >>
- name: Pack
run: >-
dotnet pack } -c Release /p:Version=} -o ./nupkgs
- name: Push to NuGet
run: >-
dotnet nuget push ./nupkgs/*.nupkg -- https://api.nuget.org/v3/index.json --api-key }
```json
---
The build matrix produces one artifact per RID. Each RID runs on the appropriate runner OS.
```yaml
strategy:
matrix:
include:
- rid: linux-x64
os: ubuntu-latest
- rid: linux-arm64
os: ubuntu-latest
- rid: osx-arm64
os: macos-latest
- rid: win-x64
os: windows-latest
```text
- **linux-arm64 on ubuntu-latest:** .NET supports cross-compilation managed (non-AOT) builds.
`dotnet publish -r linux-arm64` on an x64 runner produces a valid ARM64 binary without QEMU. For Native AOT,
cross-compiling ARM64 on an x64 runner requires the ARM64 cross-compilation toolchain (`gcc-aarch64-linux-gnu` or
equivalent). See [skill:dotnet-native-aot] cross-compile prerequisites.
- **osx-arm64:** Use `macos-latest` ( provides ARM64 runners) native compilation. Cross-compiling macOS ARM64
from Linux is not supported.
- **win-x64 on windows-latest:** Native compilation on Windows runner.
```yaml
strategy:
matrix:
include:
- rid: linux-x64
os: ubuntu-latest
- rid: linux-arm64
os: ubuntu-latest
- rid: osx-arm64
os: macos-latest
- rid: win-x64
os: windows-latest
- rid: osx-x64
os: macos-13
- rid: linux-musl-x64
os: ubuntu-latest
```text
---
Each matrix job uploads its artifact with a RID-specific name:
```yaml
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: release-}
path: |
*.tar.gz
*.zip
retention-days: 1
```text
The release job downloads all artifacts from the build matrix:
```yaml
- name: Download all artifacts
uses: actions/download-artifact@v4
with:
path: artifacts
merge-multiple:
```text
After download, `artifacts/` contains:
```text
artifacts/
mytool-1.2.3-linux-x64.tar.gz
mytool-1.2.3-linux-arm64.tar.gz
mytool-1.2.3-osx-arm64.tar.gz
mytool-1.2.3-win-x64.zip
```text
---
```yaml
- name: Generate checksums
working-directory: artifacts
run: |
-euo pipefail
shasum -a 256 *.tar.gz *.zip > checksums-sha256.txt
checksums-sha256.txt
```text
**Output format (checksums-sha256.txt):**
```text
abc123... mytool-1.2.3-linux-x64.tar.gz
def456... mytool-1.2.3-linux-arm64.tar.gz
ghi789... mytool-1.2.3-osx-arm64.tar.gz
jkl012... mytool-1.2.3-win-x64.zip
```text
```yaml
- name: Create GitHub Release
uses: softprops/action-gh-release@v2
with:
name: v}
prerelease: }
generate_release_notes:
files: |
artifacts/*.tar.gz
artifacts/*.zip
artifacts/checksums-sha256.txt
```text
`generate_release_notes: ` auto-generates release notes from merged PRs and commit messages since the last tag.
---
After the GitHub Release is published, update the Homebrew tap automatically:
```yaml
update-homebrew:
needs: release
: }
runs-on: ubuntu-latest
steps:
- name: Extract version
: version
run: >>
- uses: actions/checkout@v4
with:
repository: myorg/homebrew-tap
token: }
- name: Download checksums
run: |
-euo pipefail
curl -sL \
-o checksums.txt
- name: Update formula
run: |
-euo pipefail
VERSION=
LINUX_X64_SHA=$(grep checksums.txt | awk )
LINUX_ARM64_SHA=$(grep checksums.txt | awk )
OSX_ARM64_SHA=$(grep checksums.txt | awk )
python3 scripts/update-formula.py \
--version \
--linux-x64-sha \
--linux-arm64-sha \
--osx-arm64-sha
- name: Create PR
uses: peter-evans/create-pull-request@v6
with:
title:
commit-message:
branch:
body: |
Automated update mytool v}
Release: https://github.com/myorg/mytool/releases/tag/v}
```text
```yaml
update-winget:
needs: release
: }
runs-on: windows-latest
steps:
- name: Extract version
: version
shell: bash
run: >>
- name: Submit to winget-pkgs
uses: vedantmgoyal9/winget-releaser@main
with:
identifier: MyOrg.MyTool
version: }
installers-regex:
token: }
```text
```yaml
update-scoop:
needs: release
: }
runs-on: ubuntu-latest
steps:
- name: Extract version
: version
run: >>
- uses: actions/checkout@v4
with:
repository: myorg/scoop-mytool
token: }
- name: Download checksums
run: |
-euo pipefail
curl -sL \
-o checksums.txt
- name: Update manifest
run: |
-euo pipefail
VERSION=
WIN_X64_SHA=$(grep checksums.txt | awk )
jq --arg v --arg h \
\
bucket/mytool.json > tmp.json && tmp.json bucket/mytool.json
- name: Create PR
uses: peter-evans/create-pull-request@v6
with:
title:
commit-message:
branch:
```text
---
| Change Type | Version Bump | Example |
| -------------------------------- | ------------------ | -------------- |
| Breaking CLI flag rename/removal | Major | 1.x.x -> 2.0.0 |
| New or option | Minor | x.1.x -> x.2.0 |
| Bug fix, performance improvement | Patch | x.x.1 -> x.x.2 |
| Release candidate | Pre-release suffix | x.x.x-rc.1 |
The version flows from the git tag through `dotnet publish` into the binary:
```xml
<!-- .csproj -- Version is at publish via /p:Version -->
<PropertyGroup>
<!-- Fallback version development -->
<Version>0.0.0-dev</Version>
</PropertyGroup>
```text
```bash
$ mytool --version
1.2.3
```bash
```bash
git commit -am
git tag -a v1.2.3 -m
git push origin v1.2.3
```text
---
```yaml
```text
```yaml
permissions:
contents: write
```yaml
Use job-level permissions when different need different scopes. Never grant `write-all`.
---
1. **Do not use ` -e` without ` -o pipefail` GitHub Actions bash steps.** Without `pipefail`, a failing
piped to `` or another utility exits 0, masking the failure. Always use ` -euo pipefail`.
2. **Do not hardcode the .NET version the publish path.** Use `dotnet publish -o ./publish` to control the output
directory explicitly. Hardcoding `net8.0` artifact paths breaks when upgrading to .NET 9+.
3. **Do not skip the pre-release detection step.** Package manager submissions (Homebrew, winget, Scoop, Chocolatey,
NuGet) must be gated on stable versions. Publishing a `-rc.1` to winget-pkgs or NuGet as stable causes user
confusion.
4. **Do not use `actions/upload-artifact` v3 with `merge-multiple`.** The `merge-multiple` parameter requires
`actions/download-artifact@v4`. Using v3 silently ignores the flag and creates nested directories.
5. **Do not forget `retention-days: 1` on intermediate build artifacts.** Release artifacts are published to GitHub
Releases (permanent). Workflow artifacts are temporary and should expire quickly to save storage.
6. **Do not create GitHub Releases with `gh release create` a matrix job.** Only the release job (after all builds
complete) should create the release. Matrix upload artifacts; the release job assembles them.
---
**Primary approach:** Use Serena symbol operations efficient code navigation:
1. **Find definitions**: `serena_find_symbol` instead of text search
2. **Understand structure**: `serena_get_symbols_overview` file organization
3. **Track references**: `serena_find_referencing_symbols` impact analysis
4. **Precise edits**: `serena_replace_symbol_body` clean modifications
**When to use Serena vs traditional tools:**
- ✅ **Use Serena**: Navigation, refactoring, dependency analysis, precise edits
- ✅ **Use Read/Grep**: Reading full files, pattern matching, simple text operations
- ✅ **Fallback**: If Serena unavailable, traditional tools work fine
**Example workflow:**
```text
Read: src/Services/OrderService.cs
Grep:
serena_find_symbol:
serena_get_symbols_overview:
```
- [GitHub Actions workflow syntax](https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions)
- [softprops/action-gh-release](https://github.com/softprops/action-gh-release)
- [peter-evans/create-pull-request](https://github.com/peter-evans/create-pull-request)
- [vedantmgoyal9/winget-releaser](https://github.com/vedantmgoyal9/winget-releaser)
- [Semantic Versioning](https://semver.org/)
- [.NET versioning](https://learn.microsoft.com/en-us/dotnet/core/versions/)
- [GitHub Actions artifacts](https://docs.github.com/en/actions/using-workflows/storing-workflow-data-as-artifacts)
"version=${GITHUB_REF_NAME#v}"
"$GITHUB_OUTPUT"
# v1.2.3 → 1.2.3
### Pre-release Versions
# Pre-release tag
"Release candidate 1"
# CI detects pre-release and skips package manager submissions