diff --git a/.github/workflows/nuget-release.yml b/.github/workflows/nuget-release.yml
new file mode 100644
index 00000000..53f5daa5
--- /dev/null
+++ b/.github/workflows/nuget-release.yml
@@ -0,0 +1,148 @@
+name: Nuget-Release
+
+# Manual, versioned release of the Auriga NuGet packages (Auriga, Auriga.Xmi, Auriga.Extensions).
+# Auriga.CodeGenerator and Auriga.Reporting are IsPackable=false, so `dotnet pack` on the solution
+# produces exactly the three library packages (plus their .snupkg symbol packages). Packaging metadata,
+# SBOM generation (Microsoft.Sbom.Targets) and SourceLink are configured in Directory.Build.props.
+
+on:
+ workflow_dispatch:
+ inputs:
+ version:
+ description: 'SemVer (e.g., 1.0.0 or 1.0.0-beta.1)'
+ required: true
+ type: string
+
+permissions:
+ contents: write
+
+jobs:
+ release:
+ runs-on: ubuntu-latest
+ env:
+ DEFAULT_BRANCH: ${{ github.event.repository.default_branch }}
+
+ steps:
+ - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
+ with:
+ fetch-depth: 0
+ ref: ${{ github.event.repository.default_branch }}
+
+ - name: Validate version (SemVer)
+ run: |
+ set -euo pipefail
+ VERSION="${{ github.event.inputs.version }}"
+ if [[ "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z.-]+)?$ ]]; then
+ echo "VERSION=$VERSION" >> "$GITHUB_ENV"
+ if [[ "$VERSION" == *-* ]]; then
+ echo "PRERELEASE=true" >> "$GITHUB_ENV"
+ else
+ echo "PRERELEASE=false" >> "$GITHUB_ENV"
+ fi
+ else
+ echo "Provided version '$VERSION' is not SemVer." >&2
+ exit 1
+ fi
+
+ - name: Setup .NET
+ uses: actions/setup-dotnet@26b0ec14cb23fa6904739307f278c14f94c95bf1 # v5.4.0
+ with:
+ dotnet-version: '10.0.x'
+
+ - name: Set date
+ run: echo "DATE=$(date +'%Y-%m-%d')" >> "$GITHUB_ENV"
+
+ - name: Update CITATION.cff (version + date)
+ run: |
+ set -euo pipefail
+ # Top-level
+ sed -i "s/^version:.*/version: \"${VERSION}\"/" CITATION.cff
+ sed -i "s/^date-released:.*/date-released: \"${DATE}\"/" CITATION.cff
+ # preferred-citation (two-space indent)
+ sed -i "s/^ version:.*/ version: \"${VERSION}\"/" CITATION.cff
+ sed -i "s/^ date-released:.*/ date-released: \"${DATE}\"/" CITATION.cff
+
+ - name: Commit CITATION.cff to default branch
+ run: |
+ set -euo pipefail
+ git config user.name "github-actions[bot]"
+ git config user.email "github-actions[bot]@users.noreply.github.com"
+ git add CITATION.cff
+
+ if ! git diff --cached --quiet; then
+ git commit -m "chore: release ${VERSION} (update CITATION.cff)"
+ git push origin HEAD:${DEFAULT_BRANCH}
+ else
+ echo "No changes to CITATION.cff."
+ fi
+
+ - name: Install xmlstarlet (for parsing csproj)
+ run: |
+ sudo apt-get update
+ sudo apt-get install -y xmlstarlet
+
+ - name: Build RELEASE_NOTES.md from PackageReleaseNotes
+ run: |
+ set -euo pipefail
+ echo "The following items have been fixed in this release:" > RELEASE_NOTES.md
+ echo "" >> RELEASE_NOTES.md
+
+ mapfile -t CSPROJS < <(git ls-files '*.csproj' | sort)
+
+ for csproj in "${CSPROJS[@]}"; do
+ # PackageId (fallback to file name)
+ pkg_id="$(xmlstarlet sel -t -v '(//Project/PropertyGroup/PackageId)[1]' "$csproj" 2>/dev/null || true)"
+ if [ -z "$pkg_id" ]; then
+ pkg_id="$(basename "$csproj" .csproj)"
+ fi
+
+ # Version (fallback to the workflow input)
+ pkg_version="$(xmlstarlet sel -t -v '(//Project/PropertyGroup/Version)[1]' "$csproj" 2>/dev/null || true)"
+ if [ -z "$pkg_version" ]; then
+ pkg_version="${VERSION}"
+ fi
+
+ # Multiline PackageReleaseNotes
+ notes="$(xmlstarlet sel -t -v '(//Project/PropertyGroup/PackageReleaseNotes)[1]' "$csproj" 2>/dev/null || true)"
+ notes="$(printf "%s" "$notes" | sed -e 's/\r$//')"
+
+ if [ -n "$notes" ]; then
+ printf "**%s [%s]**\n" "$pkg_id" "$pkg_version" >> RELEASE_NOTES.md
+ while IFS= read -r line; do
+ trimmed="$(printf "%s" "$line" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')"
+ if [ -n "$trimmed" ]; then
+ cleaned="$(printf "%s" "$trimmed" | sed 's/^- \{0,1\}//')"
+ printf " - %s\n" "$cleaned" >> RELEASE_NOTES.md
+ fi
+ done <<< "$notes"
+ echo "" >> RELEASE_NOTES.md
+ fi
+ done
+
+ echo "----- RELEASE_NOTES.md -----"
+ cat RELEASE_NOTES.md
+
+ - name: Pack
+ run: dotnet pack -c Release -o ReleaseBuilds Auriga.sln
+
+ - name: Push to NuGet
+ env:
+ NUGET_API_KEY: ${{ secrets.NUGET_API_KEY }}
+ run: dotnet nuget push ReleaseBuilds/*.nupkg -k "$NUGET_API_KEY" -s https://api.nuget.org/v3/index.json --skip-duplicate
+
+ - name: Create annotated tag at this commit
+ run: |
+ set -euo pipefail
+ git tag -a "${VERSION}" -m "Release ${VERSION}"
+ git push origin "refs/tags/${VERSION}"
+
+ - name: Create draft GitHub release
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ run: |
+ set -euo pipefail
+ FLAGS=(--draft --title "Auriga ${VERSION}" --notes-file RELEASE_NOTES.md --target "${DEFAULT_BRANCH}")
+ if [ "${PRERELEASE}" = "true" ]; then
+ FLAGS+=(--prerelease)
+ fi
+ gh release create "${VERSION}" "${FLAGS[@]}"
diff --git a/CITATION.cff b/CITATION.cff
new file mode 100644
index 00000000..709ffebc
--- /dev/null
+++ b/CITATION.cff
@@ -0,0 +1,30 @@
+cff-version: 1.2.0
+message: "If you use this software, please cite it as below."
+
+title: "Auriga: A .NET library for reading, manipulating and writing Eclipse Capella models"
+abstract: "Auriga is a suite of .NET libraries for reading, manipulating and writing Eclipse Capella (Arcadia) models in XMI form, exposing the Capella semantic model as a fully resolved in-memory object graph."
+version: "0.1.0"
+date-released: "2026-07-10"
+url: "https://github.com/stariongroup/Auriga"
+
+authors:
+ - given-names: "Sam"
+ family-names: "Gerené"
+ affiliation: "Starion Group S.A."
+ orcid: "https://orcid.org/0009-0000-1848-550X"
+ - name: "Starion Group S.A."
+
+repository-code: "https://github.com/stariongroup/Auriga"
+license: "Apache-2.0"
+
+preferred-citation:
+ type: software
+ title: "Auriga: A .NET library for reading, manipulating and writing Eclipse Capella models"
+ authors:
+ - given-names: "Sam"
+ family-names: "Gerené"
+ orcid: "https://orcid.org/0009-0000-1848-550X"
+ - name: "Starion Group S.A."
+ version: "0.1.0"
+ url: "https://github.com/stariongroup/Auriga"
+ date-released: "2026-07-10"
diff --git a/Directory.Build.props b/Directory.Build.props
index a18a7330..c56e9a33 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -40,6 +40,7 @@
true
README.md
+ cdp4-icon.png
true
true
@@ -49,6 +50,7 @@
+