Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
142 changes: 142 additions & 0 deletions .github/workflows/nuget-reference-check.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
name: "nuget package reference check"

on:
push:
pull_request:
schedule:
- cron: '0 8 * * *'

jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v6.0.2
with:
fetch-depth: 2

- name: Setup .NET Environment
uses: actions/setup-dotnet@v5.1.0
with:
dotnet-version: 10.0.x

- name: Install dependencies
run: dotnet restore Kalliope.sln

- name: Build
run: dotnet build Kalliope.sln --no-restore /p:ContinuousIntegrationBuild=true

- name: Check for outdated packages
id: outdated
run: |
set -e

# Packages to ignore (SDK/runtime-managed)
IGNORE_PACKAGES="Microsoft\.NETCore\.Platforms|Microsoft\.NETCore\.Targets"

dotnet list Kalliope.sln package --outdated --include-transitive > outdated-raw.log

# Filter out ignored core packages
grep -v -E "$IGNORE_PACKAGES" outdated-raw.log > outdated.log || true

# Print full outdated report (including test projects) to action log
echo "=== Full outdated packages report ==="
cat outdated.log

# Build issue log: exclude test project sections
# dotnet list output groups packages under project headers like:
# Project `ProjectName` has the following updates available:
# We remove sections for *.Tests projects
awk '
/^Project .*.Tests/ { skip=1; next }
/^Project / { skip=0 }
!skip { print }
' outdated.log > outdated-issue.log

# Check if non-test outdated packages exist (look for > lines indicating actual packages)
if grep -q ">" outdated-issue.log; then
echo "Outdated packages found (non-test)"
echo "outdated=true" >> $GITHUB_OUTPUT
else
echo "No outdated packages found in non-test projects"
echo "outdated=false" >> $GITHUB_OUTPUT
fi

- name: Check for deprecated packages
id: deprecated
run: |
set -e
dotnet list Kalliope.sln package --deprecated --include-transitive > deprecated.log
if [ -s deprecated.log ]; then
echo "Deprecated packages found"
echo "deprecated=true" >> $GITHUB_OUTPUT
else
echo "No deprecated packages found"
echo "deprecated=false" >> $GITHUB_OUTPUT
fi

- name: Check for vulnerable packages
id: vulnerable
run: |
set -e
dotnet list Kalliope.sln package --vulnerable --include-transitive > vulnerabilities.log
if grep -q -i "\bcritical\b\|\bhigh\b\|\bmoderate\b\|\blow\b" vulnerabilities.log; then
echo "Security Vulnerabilities found"
echo "vulnerable=true" >> $GITHUB_OUTPUT
else
echo "No Security Vulnerabilities found"
echo "vulnerable=false" >> $GITHUB_OUTPUT
fi

- name: Create GitHub Issue if issues found
if: steps.outdated.outputs.outdated == 'true' || steps.deprecated.outputs.deprecated == 'true' || steps.vulnerable.outputs.vulnerable == 'true'
uses: actions/github-script@v6
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const fs = require('fs');

let issueBody = `### NuGet Package Issues Detected in [Kalliope](${process.env.GITHUB_SERVER_URL}/${process.env.GITHUB_REPOSITORY})\n\n`;

if ('${{ steps.outdated.outputs.outdated }}' === 'true') {
const outdatedLog = fs.readFileSync('outdated-issue.log', 'utf8');
issueBody += `#### Outdated Packages\n\`\`\`\n${outdatedLog}\n\`\`\`\n\n`;
}

if ('${{ steps.deprecated.outputs.deprecated }}' === 'true') {
const deprecatedLog = fs.readFileSync('deprecated.log', 'utf8');
issueBody += `#### Deprecated Packages\n\`\`\`\n${deprecatedLog}\n\`\`\`\n\n`;
}

if ('${{ steps.vulnerable.outputs.vulnerable }}' === 'true') {
const vulnerabilitiesLog = fs.readFileSync('vulnerabilities.log', 'utf8');
issueBody += `#### Vulnerable Packages\n\`\`\`\n${vulnerabilitiesLog}\n\`\`\`\n\n`;
}

issueBody += '**Action Required:** Please review and update the affected packages.';

const issueTitle = 'NuGet Package Issues Detected';
const { data: issues } = await github.rest.issues.listForRepo({
owner: context.repo.owner,
repo: context.repo.repo,
state: 'open',
});

const existingIssue = issues.find(issue => issue.title === issueTitle);

if (existingIssue) {
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: existingIssue.number,
body: `New check results:\n${issueBody}`,
});
} else {
await github.rest.issues.create({
owner: context.repo.owner,
repo: context.repo.repo,
title: issueTitle,
body: issueBody,
labels: ['dependencies', 'maintenance'],
});
}
144 changes: 144 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
name: Nuget-Release

on:
workflow_dispatch:
inputs:
version:
description: 'SemVer (e.g., 1.2.3 or 1.2.3-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@v6.0.2
with:
fetch-depth: 0
ref: ${{ env.DEFAULT_BRANCH }}

- name: Validate version (SemVer)
id: 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@v5.1.0
with:
dotnet-version: '10.0.x'

- name: Set date
run: |
DATE=$(date +'%Y-%m-%d')
echo "DATE=$DATE" >> $GITHUB_ENV

- name: Update CITATION.cff (version + date)
run: |
# 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 Kalliope.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: |
git tag -a "${VERSION}" -m "Release ${VERSION}"
git push origin "refs/tags/${VERSION}"

- name: Create draft GitHub release (attach EXE)
uses: softprops/action-gh-release@v2.5.0
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
draft: true
prerelease: ${{ env.PRERELEASE }}
name: "ECoreNetto ${{ env.VERSION }}"
tag_name: ${{ env.VERSION }}
body_path: RELEASE_NOTES.md
48 changes: 48 additions & 0 deletions CITATION.cff
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
cff-version: 1.2.0
message: "If you use this software, please cite it as below."

title: "Kalliope: a set of C# libraries used to read and write ORM2 files"
abstract: "Kalliope is a set of C# libraries used to read and write ORM2 files. Kalliope is used in Starion Group products and projects to perform code generation."
version: "0.17.1"
date-released: "2024-08-12"
url: "https://github.com/STARIONGROUP/Kalliope.git"

authors:
- given-names: "Sam"
family-names: "Gerené"
affiliation: "Starion Group S.A."
orcid: "https://orcid.org/0009-0000-1848-550X"
- given-names: Antoine
family-names: Théate
affiliation: "Starion Group S.A."
- given-names: Nathanael
family-names: Smiechowski
affiliation: "Starion Group S.A."
- given-names: Alexander
family-names: Van Delft
affiliation: "Starion Group S.A."
- name: "Starion Group S.A."

repository-code: "https://github.com/STARIONGROUP/Kalliope.git"
license: "Apache-2.0"

preferred-citation:
type: software
title: "Kalliope: a set of C# libraries used to read and write ORM2 files"
authors:
- given-names: "Sam"
family-names: "Gerené"
orcid: "https://orcid.org/0009-0000-1848-550X"
- given-names: Antoine
family-names: Théate
affiliation: "Starion Group S.A."
- given-names: Nathanael
family-names: Smiechowski
affiliation: "Starion Group S.A."
- given-names: Alexander
family-names: Van Delft
affiliation: "Starion Group S.A."
- name: "Starion Group S.A."
version: "0.17.1"
url: "https://github.com/STARIONGROUP/Kalliope.git"
date-released: "2024-08-12"
3 changes: 3 additions & 0 deletions Kalliope.sln
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
NOTICE = NOTICE
README.md = README.md
CLAUDE.md = CLAUDE.md
CITATION.cff = CITATION.cff
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Kalliope.Generator", "Kalliope.Generator\Kalliope.Generator.csproj", "{553B59EB-B9CD-4651-A9AE-2EB161F5A2A1}"
Expand All @@ -32,6 +33,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "workflows", "workflows", "{
ProjectSection(SolutionItems) = preProject
.github\workflows\codeql-analysis.yml = .github\workflows\codeql-analysis.yml
.github\workflows\CodeQuality.yml = .github\workflows\CodeQuality.yml
.github\workflows\nuget-reference-check.yml = .github\workflows\nuget-reference-check.yml
.github\workflows\release.yml = .github\workflows\release.yml
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Kalliope.OO", "Kalliope.OO\Kalliope.OO.csproj", "{FF4D9729-2E90-48A4-B41E-DF4827945BB5}"
Expand Down
2 changes: 1 addition & 1 deletion Kalliope/Kalliope.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<Description>The Kalliope POCO class library</Description>
<PackageId>Kalliope</PackageId>
<Company>Starion Group S.A.</Company>
<Copyright>Copyright 2022-2024 Starion Group S.A.</Copyright>
<Copyright>Copyright 2022-2026 Starion Group S.A.</Copyright>
<PackageProjectUrl>https://kalliope-orm.org/</PackageProjectUrl>
<PackageLicenseExpression>Apache-2.0</PackageLicenseExpression>
<RepositoryUrl>https://github.com/STARIONGROUP/Kalliope.git</RepositoryUrl>
Expand Down
Loading