Skip to content
Open
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
298 changes: 174 additions & 124 deletions .github/workflows/nuget-reference-check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,133 +6,183 @@ on:
schedule:
- cron: '0 8 * * *'

permissions:
contents: read
issues: write

jobs:
build:
nuget-package-check:
runs-on: ubuntu-latest

steps:
- name: Checkout repository
uses: actions/checkout@v6.0.2
with:
# We must fetch at least the immediate parents so that if this is
# a pull request then we can checkout the head.
fetch-depth: 2

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

- 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 SysML2.NET.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 SysML2.NET.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 SysML2.NET.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 [SysML2.NET](${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({
- 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: Check for outdated packages
id: outdated
run: |
set -e

IGNORE_PACKAGES="Microsoft\.NETCore\.Platforms|Microsoft\.NETCore\.Targets"

# Full report for the workflow logs only, including transitive packages
dotnet list SysML2.NET.sln package --outdated --include-transitive > outdated-full-raw.log
grep -v -E "$IGNORE_PACKAGES" outdated-full-raw.log > outdated-full.log || true

echo "=== Full outdated packages report including transitive packages ==="
cat outdated-full.log

# Direct/top-level outdated packages only, used for GitHub issue creation
dotnet list SysML2.NET.sln package --outdated > outdated-raw.log
grep -v -E "$IGNORE_PACKAGES" outdated-raw.log > outdated.log || true

echo "=== Direct outdated packages report used for issue detection ==="
cat outdated.log

awk '
/^Project .*.Tests/ { skip=1; next }
/^Project / { skip=0 }
!skip { print }
' outdated.log > outdated-issue.log

if grep -q "^ *>" outdated-issue.log; then
echo "Outdated direct packages found in non-test projects"
echo "outdated=true" >> $GITHUB_OUTPUT
else
echo "No outdated direct packages found in non-test projects"
echo "outdated=false" >> $GITHUB_OUTPUT
fi

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

dotnet list SysML2.NET.sln package --deprecated --include-transitive > deprecated.log

echo "=== Full deprecated packages report ==="
cat deprecated.log

awk '
/^Project .*.Tests/ { skip=1; next }
/^Project / { skip=0 }
!skip { print }
' deprecated.log > deprecated-issue.log

if grep -q "^ *>" deprecated-issue.log; then
echo "Deprecated packages found in non-test projects"
echo "deprecated=true" >> $GITHUB_OUTPUT
else
echo "No deprecated packages found in non-test projects"
echo "deprecated=false" >> $GITHUB_OUTPUT
fi

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

dotnet list SysML2.NET.sln package --vulnerable --include-transitive > vulnerabilities.log

echo "=== Full vulnerable packages report ==="
cat vulnerabilities.log

awk '
/^Project .*.Tests/ { skip=1; next }
/^Project / { skip=0 }
!skip { print }
' vulnerabilities.log > vulnerabilities-issue.log

if grep -q "^ *>" vulnerabilities-issue.log; then
echo "Security vulnerabilities found in non-test projects"
echo "vulnerable=true" >> $GITHUB_OUTPUT
else
echo "No security vulnerabilities found in non-test projects"
echo "vulnerable=false" >> $GITHUB_OUTPUT
fi

- name: Synchronize NuGet package issue
if: github.event_name != 'pull_request'
uses: actions/github-script@v8
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const fs = require('fs');

const issueTitle = 'NuGet Package Issues Detected';

const hasOutdated = '${{ steps.outdated.outputs.outdated }}' === 'true';
const hasDeprecated = '${{ steps.deprecated.outputs.deprecated }}' === 'true';
const hasVulnerable = '${{ steps.vulnerable.outputs.vulnerable }}' === 'true';

const hasIssues = hasOutdated || hasDeprecated || hasVulnerable;

const { data: issues } = await github.rest.issues.listForRepo({
owner: context.repo.owner,
repo: context.repo.repo,
title: issueTitle,
body: issueBody,
labels: ['dependencies', 'maintenance'],
state: 'open',
});
}

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

if (!hasIssues) {
if (existingIssue) {
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: existingIssue.number,
body: 'NuGet package check is clean again. Closing this issue automatically.',
});

await github.rest.issues.update({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: existingIssue.number,
state: 'closed',
});
}

return;
}

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

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

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

if (hasVulnerable) {
const vulnerabilitiesLog = fs.readFileSync('vulnerabilities-issue.log', 'utf8');
issueBody += `#### Vulnerable Packages\n\`\`\`\n${vulnerabilitiesLog}\n\`\`\`\n\n`;
}

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

if (existingIssue) {
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: existingIssue.number,
body: `New check results:\n\n${issueBody}`,
});
} else {
await github.rest.issues.create({
owner: context.repo.owner,
repo: context.repo.repo,
title: issueTitle,
body: issueBody,
});
}
2 changes: 1 addition & 1 deletion SysML2.NET.Viewer/SysML2.NET.Viewer.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="10.0.9" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="10.0.9" PrivateAssets="all" />
<PackageReference Include="ReactiveUI" Version="23.2.28" />
<PackageReference Include="Radzen.Blazor" Version="10.4.7" />
<PackageReference Include="Radzen.Blazor" Version="10.4.9" />
<PackageReference Include="Serilog.Enrichers.Environment" Version="3.0.1" />
<PackageReference Include="Serilog.Enrichers.Process" Version="3.0.0" />
<PackageReference Include="Serilog.Enrichers.Thread" Version="4.0.0" />
Expand Down
Loading