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
27 changes: 27 additions & 0 deletions .config/dotnet-tools.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"version": 1,
"isRoot": true,
"tools": {
"mindee.cli": {
"version": "4.6.0",
"commands": [
"mindee"
],
"rollForward": false
},
"dotnet-delice": {
"version": "2.1.0",
"commands": [
"dotnet-delice"
],
"rollForward": false
},
"husky": {
"version": "0.9.1",
"commands": [
"husky"
],
"rollForward": false
}
}
}
6 changes: 6 additions & 0 deletions .github/workflows/_static-analysis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,9 @@ jobs:

- name: Run dotnet format
run: dotnet format --verify-no-changes

- name: Restore local tools (dotnet-delice)
run: dotnet tool restore

- name: Check dependency licenses against whitelist
run: bash .husky/check-licenses.sh
5 changes: 3 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -374,5 +374,6 @@ _site
# StrongName files
*.snk
*.snk.b64
# Local CLI publish.
dotnet-tools.json

# dotnet-delice output
/licenses.json
78 changes: 78 additions & 0 deletions .husky/check-licenses.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
#!/usr/bin/env bash
#
# License whitelist check for NuGet dependencies.
#
# Runs `dotnet delice` and fails if any package uses a license expression that
# isn't listed in .husky/licenses.allowed, unless the package name appears in
# .husky/licenses.allowed-packages.
#
# Requires: dotnet, jq, bash. No Python.
#
set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
SLN="$SCRIPT_DIR/../Mindee.sln"
# SPDX license-list cache that delice re-creates in the repository root on each run.
SPDX_CACHE="$SCRIPT_DIR/../licenses.json"
ALLOWED_FILE="$SCRIPT_DIR/licenses.allowed"
ALLOWED_PKGS_FILE="$SCRIPT_DIR/licenses.allowed-packages"

command -v jq >/dev/null 2>&1 || {
echo "[husky] jq is required for the license check but was not found in PATH." >&2
exit 2
}

TMP_JSON="$(mktemp -t delice-XXXXXX.json)"
trap 'rm -f "$TMP_JSON" "$SPDX_CACHE"' EXIT

echo "[husky] Running dotnet delice on ${SLN} ..."
dotnet delice "$SLN" -j --json-output "$TMP_JSON" >/dev/null
Comment thread
sebastianMindee marked this conversation as resolved.

strip_comments() {
# Drop blank lines and '#' comments, trim trailing whitespace.
sed -e 's/[[:space:]]*$//' -e '/^[[:space:]]*#/d' -e '/^[[:space:]]*$/d' "$1"
}

ALLOWED_LICENSES="$(strip_comments "$ALLOWED_FILE" || true)"
ALLOWED_PACKAGES="$(strip_comments "$ALLOWED_PKGS_FILE" 2>/dev/null || true)"

# Emit one tab-separated record per package: project<TAB>name<TAB>version<TAB>expression
# We deliberately avoid jq's @tsv, which doubles backslashes (breaking matches
# against expressions like `licenses\LICENSE.txt`).
RECORDS="$(jq -r '
.projects[]
| .projectName as $p
| .licenses[]
| .expression as $e
| .packages[]
| [$p, .name, (.version // "?"), $e] | join("\t")
' "$TMP_JSON")"

violations=""
while IFS=$'\t' read -r project name version expression; do
[ -z "${name:-}" ] && continue
# Allowed license expression?
if printf '%s\n' "$ALLOWED_LICENSES" | grep -Fxq -- "$expression"; then
continue
fi
# Per-package exception?
if [ -n "$ALLOWED_PACKAGES" ] && printf '%s\n' "$ALLOWED_PACKAGES" | grep -Fxq -- "$name"; then
continue
fi
violations+=$'\n'" - ${name}@${version} (license: ${expression}) [project: ${project}]"
done <<< "$RECORDS"

if [ -n "$violations" ]; then
{
echo "Disallowed package licenses detected:"
# De-duplicate while preserving order.
printf '%s\n' "$violations" | awk 'NF && !seen[$0]++'
echo
echo "Either remove the offending dependency, add the license expression to"
echo ".husky/licenses.allowed, or add the package name to"
echo ".husky/licenses.allowed-packages after review."
} >&2
exit 1
fi

echo "License check passed: all packages use whitelisted licenses."
11 changes: 11 additions & 0 deletions .husky/licenses.allowed
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# One SPDX-style license expression per line. Blank lines and '#' comments allowed.
# Any package whose license expression is NOT in this list will fail the pre-push check,
# unless the package name appears in licenses.allowed-packages.
MIT
Apache-2.0
BSD-3-Clause
LGPL-3.0-or-later
Apache-2.0 AND MIT
Microsoft Software License
licenses\LICENSE.txt
Project References
6 changes: 6 additions & 0 deletions .husky/licenses.allowed-packages
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Per-package overrides for cases where delice cannot detect the SPDX license
# (legacy NuGet license structure). Verified manually to be acceptable.
# One "PackageName" per line (no version).
Microsoft.NETFramework.ReferenceAssemblies
Microsoft.NETFramework.ReferenceAssemblies.net472
Microsoft.NETFramework.ReferenceAssemblies.net48
22 changes: 22 additions & 0 deletions .husky/pre-commit
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"

## husky task runner examples -------------------
## Note : for local installation use 'dotnet' prefix. e.g. 'dotnet husky'

## run all tasks
#husky run

### run all tasks with group: 'group-name'
#husky run --group group-name

## run task with name: 'task-name'
#husky run --name task-name

## pass hook arguments to task
#husky run --args "$1" "$2"

## or put your custom commands -------------------
#echo 'Husky.Net is awesome!'

dotnet husky run --group pre-commit
4 changes: 4 additions & 0 deletions .husky/pre-push
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"

dotnet husky run --group pre-push
27 changes: 27 additions & 0 deletions .husky/run-unit-tests.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#!/usr/bin/env bash
#
# Run unit tests for the target frameworks that are actually supported on the
# current OS. .NET Framework targets (net472 / net48) require Windows because
# Docnet.Core's native PDF binaries don't load under Mono on *nix.
#
# Mirrors the matrix used in .github/workflows/_test-units.yml.
#
set -euo pipefail

PROJECT="tests/Mindee.UnitTests/Mindee.UnitTests.csproj"

case "$(uname -s 2>/dev/null || echo Windows)" in
MINGW*|MSYS*|CYGWIN*|Windows*)
FRAMEWORKS=("net6.0" "net8.0" "net10.0" "net472" "net48")
;;
*)
FRAMEWORKS=("net8.0" "net10.0")
;;
esac

echo "[husky] Running unit tests for: ${FRAMEWORKS[*]}"

for tfm in "${FRAMEWORKS[@]}"; do
echo "[husky] --- $tfm ---"
dotnet test "$PROJECT" -f "$tfm" --nologo -v:quiet
done
24 changes: 24 additions & 0 deletions .husky/task-runner.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"$schema": "https://alirezanet.github.io/Husky.Net/schema.json",
"tasks": [
{
"name": "dotnet-format-staged",
"group": "pre-commit",
"command": "dotnet",
"args": [ "format", "Mindee.sln", "--include", "${staged}", "--verify-no-changes" ],
"include": [ "**/*.cs" ]
},
{
"name": "build",
"group": "pre-commit",
"command": "dotnet",
"args": [ "build", "Mindee.sln", "--nologo", "-clp:NoSummary", "-v:quiet" ]
},
{
"name": "unit-tests",
"group": "pre-push",
"command": "bash",
"args": [ ".husky/run-unit-tests.sh" ]
}
]
}
Loading