* Split kondo ratchet budgets into separate prod and test files Prod and test kondo suppressions shared one .clj-kondo/ratchets.edn budget per linter, so a pile of test-code ignores could mask a prod-code regression (or vice versa) inside the same number. Adds .clj-kondo/ratchets-test.edn, tracking :ignore-counts for anything under a `test` directory, independent of the prod file's budget. :config-counts (.clj-kondo/config.edn suppressions) stays combined in the prod file -- config.edn's own scoping mixes test and prod namespaces in several groups, so it can't be reliably split per suppression. Updates every consumer: dev.kondo-ratchet's fix!/check, bin/merge-kondo-ratchets, the backport and release-cut disable scripts, the shrink workflow, and file-paths.yaml/.gitignore. * Fix test-ratchets validation and exemption-suggestion bugs from roborev fix!/check read the test ratchets file with *ratchets-file* rebound to *test-ratchets-file*, but validated it after that binding ended, so an unknown linter there was reported against the prod path instead. Validation now runs inside the binding, and both now reject a nonempty :config-counts on the test file instead of letting fix! silently drop it. kondo-insert-ignores also only ever suggested adding a new linter's :comment-exempt to the prod file, even when every unjustified occurrence was test-only. It now checks prod and test occurrences against each file's own exemptions independently and names whichever file(s) actually need it. * Dedupe test-ratchets read+validate, simplify test-occurrence? fix! and check each rebuilt the same read-validate-test-file sequence inline; extracted into read-validated-test-ratchets. test-occurrence? no longer builds a throwaway set just to check one membership. * Note what splitting :config-counts later would actually cost * Fix Eastwood reflection warning in new test helper empty-test-ratchets-file! returned an untyped value, so .getPath on it needed reflection at each call site. Hinting the return type as java.io.File fixes it -- CI's changed-tests Eastwood run caught this. * Move return type hint onto the arg vector Clj-Kondo prefers the hint on the arg vector to the one on the fn name. * Move shrink PR body file reading into dev.kondo-ratchet The bb task only parses its arguments now; reading and combining the ratchet files lives next to shrink-pr-body, with a test. * Give the test ratchets file its own header and drop its :config-counts The test file was rendered with the prod header, whose last lines point readers at ratchets-test.edn and say :config-counts "stays here" -- both wrong inside the test file. It also carried an empty :config-counts that the check rejects whenever it's nonempty. render-test writes the test file with its own header and no :config-counts, and throws on a nonempty one rather than dropping it. fix!, the normalization check, and the three-way merge (a new "test" kind) all use it.
81 lines
2.6 KiB
Bash
81 lines
2.6 KiB
Bash
#!/usr/bin/env bash
|
|
|
|
set -euo pipefail
|
|
|
|
# The only place that knows what a release branch's opt-out looks like. The cut-release workflow, the
|
|
# backport helper, and the tests all go through this function.
|
|
write_disabled_ratchets() {
|
|
local file=$1
|
|
mkdir -p "$(dirname "$file")"
|
|
printf '%s\n' \
|
|
';; Kondo ignore ratchets apply only to master; this release branch opts out.' \
|
|
';; The test and fixer recognize this explicit opt-out.' \
|
|
'{:disabled true}' \
|
|
> "$file"
|
|
}
|
|
|
|
disable_ratchets() {
|
|
local commit=$1
|
|
local file
|
|
local disabled_any=
|
|
for file in .clj-kondo/ratchets.edn .clj-kondo/ratchets-test.edn; do
|
|
[ -n "$(git diff-tree --root --no-commit-id --name-only -r "$commit" -- "$file")" ] || continue
|
|
|
|
echo "$file: disabling kondo ratchets on the release branch"
|
|
write_disabled_ratchets "$file"
|
|
git add -- "$file"
|
|
disabled_any=1
|
|
done
|
|
[ -n "$disabled_any" ] || return 0
|
|
|
|
if ! git rev-parse -q --verify CHERRY_PICK_HEAD >/dev/null; then
|
|
if ! git diff --cached --quiet HEAD; then
|
|
git commit --amend --no-edit
|
|
fi
|
|
return 0
|
|
fi
|
|
|
|
if [ -z "$(git ls-files -u)" ]; then
|
|
echo "disabled ratchet file(s) were the only conflict, finishing the cherry-pick"
|
|
if git diff --cached --quiet HEAD; then
|
|
echo "nothing left to apply, committing the backport empty"
|
|
git commit --allow-empty --no-edit
|
|
else
|
|
# GIT_EDITOR outranks core.editor, VISUAL, and EDITOR, so the continuation can never wait on
|
|
# an editor; the repository's own editor configuration is left alone.
|
|
GIT_EDITOR=true git cherry-pick --continue
|
|
fi
|
|
fi
|
|
}
|
|
|
|
cherry_pick_backport() {
|
|
local commit=$1
|
|
local status=0
|
|
git cherry-pick "$commit" || status=$?
|
|
if [ "$status" -ne 0 ] && ! git rev-parse -q --verify CHERRY_PICK_HEAD >/dev/null; then
|
|
echo "cherry-pick failed without entering a resolvable conflict state" >&2
|
|
return "$status"
|
|
fi
|
|
|
|
disable_ratchets "$commit"
|
|
if [ "$status" -ne 0 ] &&
|
|
git rev-parse -q --verify CHERRY_PICK_HEAD >/dev/null &&
|
|
[ -z "$(git ls-files -u)" ]; then
|
|
echo "cherry-pick stopped without a file conflict to resolve" >&2
|
|
return "$status"
|
|
fi
|
|
}
|
|
|
|
write_backport_script() {
|
|
local commit=$1
|
|
{
|
|
echo "#!/usr/bin/env bash"
|
|
echo "set -euo pipefail"
|
|
echo "git reset HEAD~1"
|
|
echo "rm ./backport.sh"
|
|
declare -f write_disabled_ratchets disable_ratchets cherry_pick_backport
|
|
printf 'cherry_pick_backport %q\n' "$commit"
|
|
printf '%s\n' "printf 'Resolve conflicts and force push this branch.\\n\\nTo backport translations run: bin/i18n/merge-translations <release-branch>\\n'"
|
|
} > ./backport.sh
|
|
}
|