Skip to content
This repository was archived by the owner on Jul 2, 2026. It is now read-only.

Commit fb36e2e

Browse files
committed
fix: dotnet/steep/rubocop/php-cs-fixer/hadolint hardening
- dotnet-format / dotnet-format-check: walk up looking for .sln/.csproj/ .fsproj/.vbproj before invoking; warn-and-skip if no MSBuild project found (avoids the "Could not find a MSBuild project file" crash in repos with no .NET project). - steep: warn-and-skip when no Steepfile is present in any ancestor (avoids "Cannot find Steepfile" when a Gemfile exists but no Steep config). - rubocop / rubocop-lint: when a Gemfile is found in an ancestor, export BUNDLE_GEMFILE so `bundle exec rubocop` works from PWD without "Could not locate Gemfile". Fall back to system rubocop. - php-cs-fixer: auto-pass --config=.php-cs-fixer.dist.php (or .php-cs-fixer.php) when present so prek's multi-file invocations don't trip "For multiple paths config parameter is required." - hadolint: on Darwin-arm64, prefer system-installed hadolint (Homebrew) and warn-and-skip if absent (the x86_64 binary segfaults under Rosetta on Apple Silicon, no native arm64 binary upstream).
1 parent dbc193c commit fb36e2e

7 files changed

Lines changed: 147 additions & 44 deletions

File tree

hooks/dotnet-format-check/run.sh

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,39 @@
44
# is not on PATH, prints a skip warning and exits 0.
55
set -euo pipefail
66

7-
if ! command -v dotnet >/dev/null 2>&1; then
7+
if ! command -v dotnet > /dev/null 2>&1; then
88
printf 'kreuzberg-pre-commit-hooks: skipping dotnet-format-check — `dotnet` not found on PATH.\n' >&2
99
printf ' install the .NET SDK 6+ to enable this hook.\n' >&2
1010
exit 0
1111
fi
1212

13+
# `dotnet format` requires an MSBuild project (.sln/.csproj/.fsproj/.vbproj).
14+
_find_dotnet_project() {
15+
local d="${1:-${PWD}}"
16+
while [[ "${d}" != "/" && "${d}" != "." && -n "${d}" ]]; do
17+
if compgen -G "${d}"/*.sln > /dev/null \
18+
|| compgen -G "${d}"/*.csproj > /dev/null \
19+
|| compgen -G "${d}"/*.fsproj > /dev/null \
20+
|| compgen -G "${d}"/*.vbproj > /dev/null; then
21+
return 0
22+
fi
23+
d="$(dirname "${d}")"
24+
done
25+
return 1
26+
}
27+
28+
start="${PWD}"
29+
if [[ $# -gt 0 ]]; then
30+
for arg in "$@"; do
31+
[[ "${arg}" == -* ]] && continue
32+
start="$(dirname "${arg}")"
33+
break
34+
done
35+
fi
36+
37+
if ! _find_dotnet_project "${start}"; then
38+
printf 'kreuzberg-pre-commit-hooks: skipping dotnet-format-check — no MSBuild project file (.sln/.csproj/.fsproj/.vbproj) found in or above %s.\n' "${start}" >&2
39+
exit 0
40+
fi
41+
1342
exec dotnet format --verify-no-changes "$@"

hooks/dotnet-format/run.sh

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,42 @@
44
# and exits 0.
55
set -euo pipefail
66

7-
if ! command -v dotnet >/dev/null 2>&1; then
7+
if ! command -v dotnet > /dev/null 2>&1; then
88
printf 'kreuzberg-pre-commit-hooks: skipping dotnet-format — `dotnet` not found on PATH.\n' >&2
99
printf ' install the .NET SDK 6+ to enable this hook.\n' >&2
1010
exit 0
1111
fi
1212

13+
# `dotnet format` requires an MSBuild project (.sln/.csproj/.fsproj/.vbproj).
14+
# Walk up from PWD (or the first input file's dirname) so polyrepos with the
15+
# .NET project tucked under packages/csharp/ still work; warn-and-skip if none
16+
# is found in any ancestor.
17+
_find_dotnet_project() {
18+
local d="${1:-${PWD}}"
19+
while [[ "${d}" != "/" && "${d}" != "." && -n "${d}" ]]; do
20+
if compgen -G "${d}"/*.sln > /dev/null \
21+
|| compgen -G "${d}"/*.csproj > /dev/null \
22+
|| compgen -G "${d}"/*.fsproj > /dev/null \
23+
|| compgen -G "${d}"/*.vbproj > /dev/null; then
24+
return 0
25+
fi
26+
d="$(dirname "${d}")"
27+
done
28+
return 1
29+
}
30+
31+
start="${PWD}"
32+
if [[ $# -gt 0 ]]; then
33+
for arg in "$@"; do
34+
[[ "${arg}" == -* ]] && continue
35+
start="$(dirname "${arg}")"
36+
break
37+
done
38+
fi
39+
40+
if ! _find_dotnet_project "${start}"; then
41+
printf 'kreuzberg-pre-commit-hooks: skipping dotnet-format — no MSBuild project file (.sln/.csproj/.fsproj/.vbproj) found in or above %s.\n' "${start}" >&2
42+
exit 0
43+
fi
44+
1345
exec dotnet format "$@"

hooks/hadolint/run.sh

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@
33
# Downloads the upstream hadolint release binary, sha256-verifies it against
44
# checksums.txt, caches it, and execs it with the args + files passed by
55
# pre-commit / prek.
6+
#
7+
# On Darwin-arm64 we prefer a system-installed `hadolint` (e.g. via Homebrew's
8+
# arm64 build) because upstream v2.12.0 doesn't ship a Darwin-arm64 binary and
9+
# the x86_64 binary segfaults under Rosetta 2.
610
set -euo pipefail
711

812
HOOK_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
@@ -13,12 +17,24 @@ source "${REPO_ROOT}/lib/platform.sh"
1317
# shellcheck source=../../lib/download.sh
1418
source "${REPO_ROOT}/lib/download.sh"
1519

16-
VERSION="$(grep -v '^#' "${HOOK_DIR}/version.txt" | tr -d '[:space:]')"
17-
CHECKSUMS="${HOOK_DIR}/checksums.txt"
18-
1920
os="$(detect_os)"
2021
arch="$(detect_arch)"
2122

23+
# Apple Silicon: upstream ships no Darwin-arm64 binary and the x86_64 build
24+
# segfaults under Rosetta. Prefer a system hadolint (Homebrew, MacPorts) if
25+
# present; otherwise warn-and-skip so we don't crash the whole pre-commit run.
26+
if [[ "${os}" == "macos" && "${arch}" == "aarch64" ]]; then
27+
if command -v hadolint > /dev/null 2>&1; then
28+
exec hadolint "$@"
29+
fi
30+
printf 'kreuzberg-pre-commit-hooks: skipping hadolint — no native Darwin-arm64 binary upstream and the x86_64 build segfaults under Rosetta.\n' >&2
31+
printf ' install hadolint via `brew install hadolint` to enable this hook on Apple Silicon.\n' >&2
32+
exit 0
33+
fi
34+
35+
VERSION="$(grep -v '^#' "${HOOK_DIR}/version.txt" | tr -d '[:space:]')"
36+
CHECKSUMS="${HOOK_DIR}/checksums.txt"
37+
2238
case "${os}" in
2339
linux) os_part="Linux" ;;
2440
macos) os_part="Darwin" ;;
@@ -37,12 +53,6 @@ aarch64) arch_part="arm64" ;;
3753
;;
3854
esac
3955

40-
# Upstream hadolint v2.12.0 does not publish a Darwin-arm64 binary. Apple
41-
# silicon Macs run the x86_64 build under Rosetta 2.
42-
if [[ "${os_part}" == "Darwin" && "${arch_part}" == "arm64" ]]; then
43-
arch_part="x86_64"
44-
fi
45-
4656
ext=""
4757
[[ "${os_part}" == "Windows" ]] && ext=".exe"
4858

hooks/php-cs-fixer/run.sh

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,25 @@ url="https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/releases/download/v${VERSION}/
2727

2828
phar_path="$(download_tool php-cs-fixer "${VERSION}" "${url}" "${asset_name}" "${CHECKSUMS}")"
2929

30-
exec php "${phar_path}" "$@"
30+
# php-cs-fixer requires `--config` whenever multiple positional paths are
31+
# passed and a config file exists. Auto-discover .php-cs-fixer.dist.php /
32+
# .php-cs-fixer.php in the cwd and pass `--config` explicitly so prek's
33+
# multi-file invocations don't error with "For multiple paths config parameter
34+
# is required."
35+
extra_args=()
36+
if [[ ! " $* " =~ " --config" && ! " $* " =~ " --config=" ]]; then
37+
for cfg in .php-cs-fixer.dist.php .php-cs-fixer.php; do
38+
if [[ -f "${cfg}" ]]; then
39+
extra_args+=("--config=${cfg}")
40+
break
41+
fi
42+
done
43+
fi
44+
45+
if ((${#extra_args[@]} > 0)) && [[ "${1:-}" == "fix" ]]; then
46+
cmd="$1"
47+
shift
48+
exec php "${phar_path}" "${cmd}" "${extra_args[@]}" "$@"
49+
fi
50+
51+
exec php "${phar_path}" "${extra_args[@]}" "$@"

hooks/rubocop-lint/run.sh

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,20 +5,16 @@
55
# warning and exits 0.
66
set -euo pipefail
77

8-
_pick_rubocop() {
8+
_find_gemfile() {
99
local start_dir="${1:-${PWD}}"
1010
local d="${start_dir}"
11-
while [[ "${d}" != "/" && "${d}" != "." ]]; do
12-
if [[ -f "${d}/Gemfile" ]] && command -v bundle >/dev/null 2>&1; then
13-
printf 'bundle\n'
11+
while [[ "${d}" != "/" && "${d}" != "." && -n "${d}" ]]; do
12+
if [[ -f "${d}/Gemfile" ]]; then
13+
printf '%s/Gemfile\n' "${d}"
1414
return 0
1515
fi
1616
d="$(dirname "${d}")"
1717
done
18-
if command -v rubocop >/dev/null 2>&1; then
19-
printf 'rubocop\n'
20-
return 0
21-
fi
2218
return 1
2319
}
2420

@@ -28,14 +24,15 @@ else
2824
start="${PWD}"
2925
fi
3026

31-
if ! mode="$(_pick_rubocop "${start}")"; then
32-
printf 'kreuzberg-pre-commit-hooks: skipping rubocop-lint — `rubocop` not on PATH and no `Gemfile`/`bundle` available.\n' >&2
33-
printf ' install rubocop via `gem install rubocop` or add it to your Gemfile.\n' >&2
34-
exit 0
27+
if gemfile="$(_find_gemfile "${start}")" && command -v bundle > /dev/null 2>&1; then
28+
export BUNDLE_GEMFILE="${gemfile}"
29+
exec bundle exec rubocop "$@"
3530
fi
3631

37-
if [[ "${mode}" == "bundle" ]]; then
38-
exec bundle exec rubocop "$@"
32+
if command -v rubocop > /dev/null 2>&1; then
33+
exec rubocop "$@"
3934
fi
4035

41-
exec rubocop "$@"
36+
printf 'kreuzberg-pre-commit-hooks: skipping rubocop-lint — `rubocop` not on PATH and no `Gemfile`/`bundle` available.\n' >&2
37+
printf ' install rubocop via `gem install rubocop` or add it to your Gemfile.\n' >&2
38+
exit 0

hooks/rubocop/run.sh

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,16 @@ set -euo pipefail
77

88
# Pick the right invocation. Walk up from the first input file (or pwd) looking
99
# for a Gemfile so projects with managed gems get the bundled rubocop.
10-
_pick_rubocop() {
10+
_find_gemfile() {
1111
local start_dir="${1:-${PWD}}"
1212
local d="${start_dir}"
13-
while [[ "${d}" != "/" && "${d}" != "." ]]; do
14-
if [[ -f "${d}/Gemfile" ]] && command -v bundle >/dev/null 2>&1; then
15-
printf 'bundle\n'
13+
while [[ "${d}" != "/" && "${d}" != "." && -n "${d}" ]]; do
14+
if [[ -f "${d}/Gemfile" ]]; then
15+
printf '%s/Gemfile\n' "${d}"
1616
return 0
1717
fi
1818
d="$(dirname "${d}")"
1919
done
20-
if command -v rubocop >/dev/null 2>&1; then
21-
printf 'rubocop\n'
22-
return 0
23-
fi
2420
return 1
2521
}
2622

@@ -30,14 +26,15 @@ else
3026
start="${PWD}"
3127
fi
3228

33-
if ! mode="$(_pick_rubocop "${start}")"; then
34-
printf 'kreuzberg-pre-commit-hooks: skipping rubocop — `rubocop` not on PATH and no `Gemfile`/`bundle` available.\n' >&2
35-
printf ' install rubocop via `gem install rubocop` or add it to your Gemfile.\n' >&2
36-
exit 0
29+
if gemfile="$(_find_gemfile "${start}")" && command -v bundle > /dev/null 2>&1; then
30+
export BUNDLE_GEMFILE="${gemfile}"
31+
exec bundle exec rubocop -A "$@"
3732
fi
3833

39-
if [[ "${mode}" == "bundle" ]]; then
40-
exec bundle exec rubocop -A "$@"
34+
if command -v rubocop > /dev/null 2>&1; then
35+
exec rubocop -A "$@"
4136
fi
4237

43-
exec rubocop -A "$@"
38+
printf 'kreuzberg-pre-commit-hooks: skipping rubocop — `rubocop` not on PATH and no `Gemfile`/`bundle` available.\n' >&2
39+
printf ' install rubocop via `gem install rubocop` or add it to your Gemfile.\n' >&2
40+
exit 0

hooks/steep/run.sh

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,28 @@
44
# directly. If neither is available, prints a skip warning and exits 0.
55
set -euo pipefail
66

7+
_find_steepfile() {
8+
local d="${1:-${PWD}}"
9+
while [[ "${d}" != "/" && "${d}" != "." && -n "${d}" ]]; do
10+
if [[ -f "${d}/Steepfile" ]]; then
11+
return 0
12+
fi
13+
d="$(dirname "${d}")"
14+
done
15+
return 1
16+
}
17+
718
_pick_steep() {
819
local start_dir="${1:-${PWD}}"
920
local d="${start_dir}"
1021
while [[ "${d}" != "/" && "${d}" != "." ]]; do
11-
if [[ -f "${d}/Gemfile" ]] && command -v bundle >/dev/null 2>&1; then
22+
if [[ -f "${d}/Gemfile" ]] && command -v bundle > /dev/null 2>&1; then
1223
printf 'bundle\n'
1324
return 0
1425
fi
1526
d="$(dirname "${d}")"
1627
done
17-
if command -v steep >/dev/null 2>&1; then
28+
if command -v steep > /dev/null 2>&1; then
1829
printf 'steep\n'
1930
return 0
2031
fi
@@ -27,6 +38,12 @@ else
2738
start="${PWD}"
2839
fi
2940

41+
if ! _find_steepfile "${start}"; then
42+
printf 'kreuzberg-pre-commit-hooks: skipping steep — no Steepfile found in or above %s.\n' "${start}" >&2
43+
printf ' initialize steep via `steep init` to enable this hook.\n' >&2
44+
exit 0
45+
fi
46+
3047
if ! mode="$(_pick_steep "${start}")"; then
3148
printf 'kreuzberg-pre-commit-hooks: skipping steep — `steep` not on PATH and no `Gemfile`/`bundle` available.\n' >&2
3249
printf ' install steep via `gem install steep` or add it to your Gemfile.\n' >&2

0 commit comments

Comments
 (0)