Skip to content

Commit e675f7e

Browse files
authored
Merge pull request #7 from pkgdiff-dev/chore/trim-comments
chore: trim code comments across the repo
2 parents 8cadb80 + 232913b commit e675f7e

290 files changed

Lines changed: 387 additions & 1886 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎.github/dependabot.yml‎

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,4 @@
1-
# Monthly update PRs into develop: one batch a month, merged as one PR so develop deploys once.
2-
# The cooldown holds a release back for 7 days so a broken or hijacked version is caught upstream
3-
# first; security updates ignore both the schedule and the cooldown.
4-
#
5-
# Every ignore rule below is a deliberate hold; its reason is the
6-
# comment next to it.
1+
# The 7-day cooldown lets a broken or hijacked release be caught upstream first.
72
version: 2
83
updates:
94
- package-ecosystem: "nuget"
@@ -21,7 +16,7 @@ updates:
2116
patterns: ["*"]
2217
exclude-patterns: ["QuestPDF"]
2318
update-types: [minor, patch]
24-
# Always alone: a QuestPDF bump must pass .github/scripts/questpdf-cpu-check.sh before it is merged
19+
# Alone: a QuestPDF bump must pass .github/scripts/questpdf-cpu-check.sh before merging
2520
questpdf:
2621
patterns: ["QuestPDF"]
2722
ignore:
@@ -79,8 +74,7 @@ updates:
7974
- dependency-name: "@types/node"
8075
versions: [">=23"]
8176

82-
# One entry for all three Dockerfiles: the SDK and runtime references are shared between
83-
# Backend and the QuestPDF harness and must move in one PR (see "SDK image" in the register)
77+
# One entry so the SDK/runtime references shared across Dockerfiles move in one PR
8478
- package-ecosystem: "docker"
8579
directories:
8680
- "/src/backend"
@@ -95,8 +89,7 @@ updates:
9589
commit-message:
9690
prefix: "chore(deps)"
9791
groups:
98-
# Dependabot names a Docker dependency by its image path without the registry:
99-
# dotnet/sdk and dotnet/aspnet, not mcr.microsoft.com/dotnet/...
92+
# Dependabot names Docker images without the registry (dotnet/sdk, not mcr.microsoft.com/...)
10093
dotnet-images:
10194
patterns: ["dotnet/*"]
10295
other-images:

‎.github/scripts/check-deps.sh‎

Lines changed: 8 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,6 @@
11
#!/usr/bin/env bash
2-
# Supply-chain gate for pkgdiff: NuGet, npm and (optionally) the built images.
3-
#
4-
# bash .github/scripts/check-deps.sh run from any directory
5-
#
6-
# TRIVY=1 also scan ${BACKEND_IMAGE:-ghcr.io/pkgdiff-dev/pkgdiff-backend:local} and
7-
# ${FRONTEND_IMAGE:-ghcr.io/pkgdiff-dev/pkgdiff-frontend:local} with the
8-
# pinned Trivy image (the defaults are what docker-compose.build.yml builds)
9-
# CHECK_DEPS_DOCKER=auto auto (default): use dotnet / npm from PATH, and the pinned SDK / Node
10-
# image for a tool that is missing; 1: always containers; 0: never
11-
# PKGDIFF_ROOT=<dir> check another checkout (default: the checkout this script is in)
12-
#
13-
# Checks (every check runs, also after a failure):
14-
# sdk-image-pin the SDK image is pinned by digest and is the same reference in
15-
# src/backend/Dockerfile, src/backend/Directory.Build.props and the QuestPDF harness
16-
# nuget-locked-restore dotnet restore --locked-mode with the audit gate (lock drift, NU1901-NU1904)
17-
# nuget-vulnerable dotnet list package --vulnerable --include-transitive, read as JSON
18-
# npm-audit-prod npm audit --omit=dev (production dependencies must be clean)
19-
# npm-audit-high .github/scripts/npm-audit-gate.mjs with src/frontend/audit-allowlist.json
20-
# trivy-backend TRIVY=1 only: fixable HIGH/CRITICAL in the backend image
21-
# trivy-frontend TRIVY=1 only: fixable HIGH/CRITICAL in the frontend image
22-
#
23-
# Output: one "PASS <check>" or "FAIL <check>: <detail>" line per check (evidence is indented
24-
# above it), then "check-deps: N passed, M failed". A check that could not be carried out is a
25-
# FAIL whose detail starts with "could not check"; it is never reported as a pass.
26-
# Exit status: 0 when every check passed, otherwise 1.
27-
#
28-
# The checkout is never modified: the manifests are copied to a temporary directory and the
29-
# tools run on that copy, either on this machine or inside a container.
2+
# Supply-chain gate: NuGet and npm audits, plus image scans with TRIVY=1. Exit 0 when all pass.
3+
# Env: TRIVY=1, CHECK_DEPS_DOCKER=auto|1|0, PKGDIFF_ROOT=<dir>, BACKEND_IMAGE, FRONTEND_IMAGE.
304
set -uo pipefail
315

326
export DOTNET_CLI_UI_LANGUAGE=en DOTNET_NOLOGO=1 DOTNET_CLI_TELEMETRY_OPTOUT=1
@@ -51,8 +25,7 @@ case "$MODE" in
5125
;;
5226
esac
5327

54-
# Git Bash rewrites arguments that look like POSIX paths (/work, /var/run/docker.sock) before
55-
# docker.exe sees them; turn that off and use the socket form Docker Desktop accepts.
28+
# Git Bash rewrites POSIX-looking arguments before docker.exe sees them; turn that off.
5629
DOCKER_SOCKET='/var/run/docker.sock'
5730
case "$(uname -s 2>/dev/null)" in
5831
MINGW* | MSYS* | CYGWIN*)
@@ -121,21 +94,18 @@ one_line() {
12194
tr '\r\n' ' ' | sed 's/[[:space:]][[:space:]]*/ /g; s/^ //; s/ $//'
12295
}
12396

124-
# Prints the image of the "AS build" stage of a Dockerfile.
12597
build_stage_image() {
12698
[ -f "$1" ] || return 1
12799
tr -d '\r' <"$1" |
128100
sed -n 's/^FROM[[:space:]][[:space:]]*\([^[:space:]][^[:space:]]*\)[[:space:]][[:space:]]*[Aa][Ss][[:space:]][[:space:]]*build[[:space:]]*$/\1/p' |
129101
head -n 1
130102
}
131103

132-
# A status that decides something never comes from `writer | grep -q`: under pipefail a writer
133-
# killed by SIGPIPE makes a match read as "no match". These tests read a here-string or a file.
104+
# No `writer | grep -q` for decisions: under pipefail a SIGPIPE'd writer turns a match into a miss.
134105
is_pinned() {
135106
grep -Eq '^[A-Za-z0-9][A-Za-z0-9./_-]*:[A-Za-z0-9._-]+@sha256:[0-9a-f]{64}$' <<<"$1"
136107
}
137108

138-
# Decides whether a tool set runs in a container: 0 = container, 1 = this machine.
139109
use_container() {
140110
local tool
141111
case "$MODE" in
@@ -148,9 +118,7 @@ use_container() {
148118
return 1
149119
}
150120

151-
# run_in_container <image> <dir> [docker create options]
152-
# Copies <dir> to /work in a fresh container, runs /work/run.sh there and copies /work/out back.
153-
# No bind mount is used, so nothing depends on how this machine shares its file system with Docker.
121+
# Copies files in and out instead of bind-mounting, so host file sharing with Docker doesn't matter.
154122
run_in_container() {
155123
local image="$1" dir="$2" cid rc
156124
shift 2
@@ -169,8 +137,6 @@ run_in_container() {
169137
return "$rc"
170138
}
171139

172-
# ---------------------------------------------------------------- sdk-image-pin
173-
174140
check_sdk_image_pin() {
175141
local name='sdk-image-pin'
176142
local dockerfile="$ROOT/src/backend/Dockerfile"
@@ -205,8 +171,6 @@ check_sdk_image_pin() {
205171
pass "$name"
206172
}
207173

208-
# ---------------------------------------------------------------- NuGet
209-
210174
prepare_nuget() {
211175
local dir="$1" rel
212176
mkdir -p "$dir" || return 1
@@ -240,7 +204,6 @@ echo "$?" >out/vulnerable.rc
240204
EOF
241205
}
242206

243-
# Unique "error XX0000: message" lines of a restore log, without the trailing "[project path]".
244207
restore_errors() {
245208
tr -d '\r' <"$1" | sed -n 's/.*\(error [A-Z][A-Z]*[0-9][0-9]*: .*\)$/\1/p' | sed 's/ \[[^][]*\]$//' | sort -u
246209
}
@@ -286,11 +249,9 @@ check_nuget() {
286249
return
287250
fi
288251

289-
# nuget-locked-restore
290252
rc="$(read_rc "$out/locked-restore.rc")"
291253
if [ "$rc" = "0" ] && grep -Eq 'NU190[05]' "$out/locked-restore.log"; then
292-
# With packages in the local cache, a restore still succeeds when the advisory data cannot be
293-
# downloaded; it only warns (NU1900 / NU1905). The audit did not run, so this is not a pass.
254+
# A cached restore succeeds with only a warning when advisory data can't load: no audit ran.
294255
tr -d '\r' <"$out/locked-restore.log" | grep -oE 'warning NU190[05]: [^[]*' | sort -u | evidence
295256
unchecked nuget-locked-restore "the restore succeeded, but the advisory data could not be loaded (NU1900/NU1905), so the audit did not run"
296257
elif [ "$rc" = "0" ]; then
@@ -315,7 +276,6 @@ check_nuget() {
315276
fi
316277
fi
317278

318-
# nuget-vulnerable
319279
rc="$(read_rc "$out/plain-restore.rc")"
320280
if [ "$rc" != "0" ]; then
321281
restore_errors "$out/plain-restore.log" 2>/dev/null | head -n 10 | evidence
@@ -343,7 +303,6 @@ check_nuget() {
343303
return
344304
fi
345305
if grep -q '"vulnerabilities"' "$out/vulnerable.json"; then
346-
# The report lists only affected packages, so every id / resolvedVersion pair in it is a finding.
347306
findings="$(grep -oE '"(id|resolvedVersion|severity|advisoryurl)": *"[^"]*"' "$out/vulnerable.json" |
348307
awk -F'"' '
349308
$2 == "id" { id = $4 }
@@ -358,8 +317,6 @@ check_nuget() {
358317
pass nuget-vulnerable
359318
}
360319

361-
# ---------------------------------------------------------------- npm
362-
363320
prepare_npm() {
364321
local dir="$1" file
365322
mkdir -p "$dir/Frontend" "$dir/scripts" || return 1
@@ -437,7 +394,7 @@ check_npm() {
437394
return
438395
fi
439396

440-
# npm-audit-prod: npm audit --omit=dev exits non-zero on findings and on errors; the JSON tells them apart.
397+
# npm audit exits non-zero on findings and on errors; only the JSON tells them apart.
441398
rc="$(read_rc "$out/audit-prod.rc")"
442399
if ! grep -q '"auditReportVersion"' "$out/audit-prod.json" 2>/dev/null; then
443400
cat "$out/audit-prod.json" "$out/audit-prod.err" 2>/dev/null | tail -n 10 | evidence
@@ -451,13 +408,9 @@ check_npm() {
451408
fail npm-audit-prod "production dependencies have advisories: $(printf '%s' "$packages" | one_line)"
452409
fi
453410

454-
# npm-audit-high: replaces a bare `npm audit --audit-level=high`, which cannot tell a reviewed,
455-
# time-boxed exception from a new advisory. The gate keeps its own 0 / 1 / 2 exit status visible.
456411
rc="$(read_rc "$out/gate.rc")"
457412
case "$rc" in
458413
0)
459-
# Only the entries of the "Accepted exceptions" block are reviewed exceptions. The "Not gated"
460-
# blocks list advisories below high that nobody reviewed; they keep their own label.
461414
tr -d '\r' <"$out/gate.log" | sed -n \
462415
-e '1p' \
463416
-e '/^Accepted exceptions/,/^$/s/^ - \(GHSA-.*\)$/accepted exception: \1/p' \
@@ -481,8 +434,6 @@ check_npm() {
481434
esac
482435
}
483436

484-
# ---------------------------------------------------------------- Trivy
485-
486437
check_trivy() {
487438
local name="$1" image="$2" log="$WORK/$1.log" rc detail
488439

@@ -513,24 +464,16 @@ check_trivy() {
513464
unchecked "$name" "trivy exit 0, but it detected no OS packages in $image, so nothing was scanned"
514465
fi
515466
elif [ "$rc" -eq 1 ] && grep -Eq '^Total: [1-9][0-9]* \(' "$log"; then
516-
# Exit 1 together with a report is the only result that means "findings".
517-
# grep reads the file itself: behind a pipe, `grep -q` stops at the first match, the writer
518-
# dies of SIGPIPE on a large report, and pipefail turns the match into "false". The pattern
519-
# has no end anchor, so a trailing CR does not matter.
520-
# The whole report: whoever fixes the image needs the package and the fixed version.
467+
# Only exit 1 together with a report means findings.
521468
grep -v "$(printf '\tINFO\t')" "$log" | evidence
522469
fail "$name" "fixable HIGH/CRITICAL findings in $image: $(tr -d '\r' <"$log" | grep -E '^Total: ' | one_line)"
523470
else
524-
# No report: the scanner never started (docker run exits 125, 126 or 127 when the image cannot
525-
# be pulled or run) or it stopped before the scan finished. Nothing is known about the image.
526471
tail -n 10 "$log" | evidence
527472
detail="$(grep -E 'FATAL|[Ee]rror' "$log" | head -n 1 | one_line)"
528473
unchecked "$name" "trivy did not complete (exit $rc)${detail:+: $detail}"
529474
fi
530475
}
531476

532-
# ---------------------------------------------------------------- run
533-
534477
echo "check-deps: root $ROOT"
535478

536479
check_sdk_image_pin

‎.github/scripts/questpdf-cpu-check.sh‎

Lines changed: 4 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,5 @@
11
#!/usr/bin/env bash
2-
# QuestPDF CPU gate: renders the PDF export document inside a Linux container and reports
3-
# whether the QuestPDF native library works on a CPU without AVX2 (the production CPU is
4-
# an Ivy Bridge Xeon: AVX, but no AVX2, FMA or BMI2).
5-
#
6-
# --native render on the real CPU of this machine. Run it on the production
7-
# server before the backend is recreated with a new QuestPDF version.
8-
# --emulate render under QEMU with the IvyBridge CPU model, after a self-test
9-
# proves that the emulator really traps AVX2, FMA and BMI2.
10-
# --version <x> QuestPDF version to test (default: src/backend/Directory.Packages.props)
11-
#
12-
# Everything runs in containers; nothing is executed on the host itself.
2+
# Checks in containers that QuestPDF renders on a CPU without AVX2, FMA or BMI2 (production).
133
# Exit status: 0 = PASS, 1 = FAIL, 2 = usage error.
144
set -euo pipefail
155

@@ -67,8 +57,7 @@ ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
6757
CONTEXT="$ROOT/.github/scripts/questpdf-cpu-check"
6858

6959
if [ -z "$VERSION" ]; then
70-
# sed stops at the first match itself. With `| head -n 1`, a second matching line could kill
71-
# sed with SIGPIPE, and under `set -e -o pipefail` that ends the script without a message.
60+
# sed quits itself: `| head -n 1` could SIGPIPE sed and silently abort under pipefail.
7261
VERSION="$(sed -n '/<PackageVersion Include="QuestPDF" Version="/{s/.*<PackageVersion Include="QuestPDF" Version="\([^"]*\)".*/\1/p;q;}' "$ROOT/src/backend/Directory.Packages.props")"
7362
fi
7463

@@ -107,8 +96,6 @@ fi
10796
OUT=""
10897
STATUS=0
10998

110-
# Runs a command in the harness image with a hard time limit, no network and capped memory.
111-
# The output lands in OUT and the exit status in STATUS.
11299
capture() {
113100
local seconds="$1"
114101
shift
@@ -146,8 +133,7 @@ if [ "$MODE" = "native" ]; then
146133
exit 0
147134
fi
148135

149-
# 1. Detector self-test: a passing Ivy Bridge render only means something if the emulator
150-
# kills a process that uses an instruction Ivy Bridge does not have.
136+
# A pass only means something if the emulator kills instructions Ivy Bridge lacks.
151137
for PROBE in avx2 fma bmi2; do
152138
MARKER="$(echo "$PROBE" | tr '[:lower:]' '[:upper:]')_EXECUTED"
153139

@@ -167,14 +153,13 @@ for PROBE in avx2 fma bmi2; do
167153
fi
168154
done
169155

170-
# 2. The emulator must be able to host .NET at all, otherwise a failure below says nothing.
156+
# The emulator must host .NET at all, or a failure below says nothing.
171157
capture 600 qemu-x86_64 -cpu max "$DOTNET" "$HARNESS"
172158
show "render under -cpu max"
173159
if [ "$STATUS" -ne 0 ] || ! has "^PDF_OK "; then
174160
fail "the emulator could not host the render under -cpu max (exit $STATUS); this says nothing about Ivy Bridge"
175161
fi
176162

177-
# 3. The actual gate: no AVX2 and a valid PDF.
178163
capture 600 qemu-x86_64 -cpu IvyBridge "$DOTNET" "$HARNESS"
179164
show "render under -cpu IvyBridge"
180165
if ! has "AVX2=False"; then

‎.github/scripts/questpdf-cpu-check/Dockerfile‎

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,22 @@
1-
# Harness images for .github/scripts/questpdf-cpu-check.sh. They are never deployed or pushed.
2-
# Same SDK and runtime references as src/backend/Dockerfile.
1+
# Harness for .github/scripts/questpdf-cpu-check.sh; same SDK/runtime refs as src/backend/Dockerfile.
32
FROM mcr.microsoft.com/dotnet/sdk:10.0.402-noble@sha256:0d99ebf1ccad15037b5c98c9fe8979d6b8dbac23812feae2277a0b277b5c5ffa AS build
43
ARG QUESTPDF_VERSION
54
WORKDIR /src
65
COPY QuestPdfCpuCheck.csproj Program.cs ./
76
RUN test -n "${QUESTPDF_VERSION}" \
87
&& dotnet publish QuestPdfCpuCheck.csproj -c Release -r linux-x64 --self-contained false -o /app -p:QuestPdfVersion=${QUESTPDF_VERSION}
98

10-
# Renders on the real CPU of the machine that runs the container
119
FROM mcr.microsoft.com/dotnet/aspnet:10.0.13-noble@sha256:d5633778c754e89a386882eddf8dbee6942447a8a4b8267c19cf1e1158d0b0ac AS native
1210
WORKDIR /app
1311
COPY --from=build /app .
1412
ENTRYPOINT ["dotnet", "/app/QuestPdfCpuCheck.dll"]
1513

16-
# QEMU 8.2 from Ubuntu 24.04 crashes as soon as .NET reads /proc/self/maps.
17-
# Ubuntu 26.04 ships QEMU 10.2 as a static binary, which also runs on the 24.04 runtime image.
14+
# Older QEMU crashes when .NET reads /proc/self/maps; this static build also runs on 24.04.
1815
FROM ubuntu:26.04@sha256:f144425ff09be612d6d9ad965196e9cdc23dae1f42110a8a11a3e9a8198759f7 AS qemu
1916
RUN apt-get update \
2017
&& apt-get install -y --no-install-recommends qemu-user \
2118
&& rm -rf /var/lib/apt/lists/*
2219

23-
# Renders under QEMU user-mode emulation with a chosen CPU model
2420
FROM mcr.microsoft.com/dotnet/aspnet:10.0.13-noble@sha256:d5633778c754e89a386882eddf8dbee6942447a8a4b8267c19cf1e1158d0b0ac AS emulate
2521
RUN apt-get update \
2622
&& apt-get install -y --no-install-recommends gcc libc6-dev \

‎.github/scripts/questpdf-cpu-check/Program.cs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313

1414
QuestPDF.Settings.License = LicenseType.Community;
1515

16-
// The missing-glyph switch was renamed in 2026.9; reflection keeps one source for every version
16+
// The missing-glyph switch was renamed between versions; reflection handles both names
1717
var glyphSetting = new[] { "ThrowOnMissingTextGlyphs", "CheckIfAllTextGlyphsAreAvailable" }
1818
.Select(name => typeof(QuestPDF.Settings).GetProperty(name, BindingFlags.Public | BindingFlags.Static))
1919
.FirstOrDefault(property => property is { CanWrite: true });

‎.github/workflows/ci.yml‎

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
# Runs on every pull request into develop or master, and as the gate of the publish workflow.
2-
# No toolchain is installed on the runner: the tests run inside the SDK and Node images pinned in
3-
# src/backend/Dockerfile and src/frontend/Dockerfile, so CI uses exactly what the published images use.
1+
# PR gate and publish gate; runs inside the SDK and Node images the Dockerfiles pin.
42
name: CI
53

64
on:
@@ -25,8 +23,7 @@ jobs:
2523
with:
2624
persist-credentials: false
2725

28-
# The database tests run against the PostgreSQL image docker-compose.yml pins; without a server
29-
# they would be skipped. The password belongs to this throwaway container only.
26+
# Without a database server the database tests would be skipped
3027
- name: Run the tests in the pinned SDK image, against the pinned PostgreSQL
3128
run: |
3229
sdk="$(sed -n 's/^FROM \(mcr\.microsoft\.com\/dotnet\/sdk:[^ ]*\) AS build.*/\1/p' src/backend/Dockerfile)"

‎.github/workflows/deploy.yml‎

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,4 @@
1-
# Runs deploy/remote.sh on the server over SSH.
2-
# - Automatically: publish.yml calls it after the images of a push to develop are published,
3-
# while the repository variable PKGDIFF_AUTO_DEPLOY is "true".
4-
# - By hand: Actions > Deploy > Run workflow (deploy a tag, roll back, or show the status).
5-
# It does nothing until these repository secrets exist (docs/ops/deploy-ghcr.md):
6-
# DEPLOY_HOST, DEPLOY_USER, DEPLOY_SSH_KEY, DEPLOY_KNOWN_HOSTS; optional DEPLOY_PORT, DEPLOY_PATH
1+
# Runs deploy/remote.sh on the server over SSH; called by publish.yml or run by hand.
72
name: Deploy
83

94
on:
@@ -39,7 +34,6 @@ jobs:
3934
environment: production
4035
runs-on: ubuntu-24.04
4136
timeout-minutes: 20
42-
# One deploy at a time, in the order they were started; a running one is never cancelled
4337
concurrency:
4438
group: deploy-production
4539
cancel-in-progress: false
@@ -87,10 +81,7 @@ jobs:
8781
request="$ACTION"
8882
if [ "$ACTION" = deploy ]; then request="deploy $TAG $REVISION"; fi
8983
90-
# Every word of the request was checked above. A key installed with remote.sh as its forced
91-
# command ignores the script path given here and reads only the request.
92-
# The log of this job may be public: it shows the "deploy:" lines of the server only, the full
93-
# output (paths, container state) stays in deploy.log on the runner and on the server
84+
# The job log may be public: show only the server's "deploy:" lines
9485
status=0
9586
ssh -i ~/.ssh/deploy_key -o IdentitiesOnly=yes -o BatchMode=yes -o StrictHostKeyChecking=yes \
9687
-o ServerAliveInterval=30 -o ServerAliveCountMax=10 \

0 commit comments

Comments
 (0)