From 1e8f4b54906a8769a30d00427cb17fc56f8b204c Mon Sep 17 00:00:00 2001 From: Orkun Manap <31966136+manaporkun@users.noreply.github.com> Date: Tue, 2 Jun 2026 01:06:16 +0200 Subject: [PATCH] ci: add min-API lint guarding the Unity 2021.3 floor The dev project and Unity test job both run on 6000.3, so they can't catch APIs that fail to compile on an early 2021.3.x consumer (the class of bug from issue #11 / the FindAnyObjectByType fix). This license-free static check flags Find*ByType usage that is NOT behind a version guard; an awk pass tracks #if/#elif/#else/#endif nesting so guarded usage (#if UNITY_2023_1_OR_NEWER ... #else FindObjectOfType) is allowed. Verified: passes on current sources, catches an unguarded control. --- .github/workflows/min-api-lint.yml | 63 ++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 .github/workflows/min-api-lint.yml diff --git a/.github/workflows/min-api-lint.yml b/.github/workflows/min-api-lint.yml new file mode 100644 index 0000000..1739a60 --- /dev/null +++ b/.github/workflows/min-api-lint.yml @@ -0,0 +1,63 @@ +name: Min-API Lint + +# Guards the declared minimum Unity version (package.json `unity` = 2021.3). The dev project and +# the Unity test job both run on Unity 6000.3, so they cannot catch APIs that fail to compile on an +# early 2021.3.x consumer. This license-free static check flags such APIs when they are used WITHOUT +# a version guard. It is a heuristic (not a real 2021.3 compile), focused on the Find*ByType family +# that previously broke the floor; guarded usage (#if UNITY_..._OR_NEWER ... #else FindObjectOfType) +# is allowed. + +on: + push: + branches: + - main + paths: + - "Packages/**/*.cs" + - ".github/workflows/min-api-lint.yml" + pull_request: + paths: + - "Packages/**/*.cs" + - ".github/workflows/min-api-lint.yml" + +jobs: + min-api-lint: + name: Min-API lint (Unity 2021.3 floor) + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Scan for unguarded post-2021.3 APIs + run: | + set -uo pipefail + PKG="Packages/com.orkunmanap.runtime-transform-handles" + + # APIs introduced after 2021.3.0 (Find*ByType: 2021.3.18f1 / 2022.2). Add more here as + # the floor concern grows. FindObjectOfType (the pre-2021.3 API) is intentionally allowed. + DENY='FindAnyObjectByType|FindFirstObjectByType|FindObjectsByType' + + # awk tracks #if/#elif/#else/#endif nesting and marks a level "version-guarded" when its + # condition mentions UNITY_ or *_OR_NEWER. A denied API is reported only when it sits + # outside every version-guarded region (comment-only lines are ignored). + HITS=$(while IFS= read -r -d '' f; do + awk -v deny="$DENY" -v file="$f" ' + function isver(s){ return (s ~ /UNITY_[0-9]/ || s ~ /OR_NEWER/) } + /^[ \t]*#[ \t]*if/ { depth++; g[depth]=isver($0)?1:0; next } + /^[ \t]*#[ \t]*elif/ { if(depth>0 && isver($0)) g[depth]=1; next } + /^[ \t]*#[ \t]*else/ { next } + /^[ \t]*#[ \t]*endif/ { if(depth>0) depth--; next } + { + ing=0; for(i=1;i<=depth;i++) if(g[i]) ing=1 + if(ing==0 && $0 ~ ("(" deny ")") && $0 !~ /^[ \t]*\/\//) + printf "%s:%d:%s\n", file, NR, $0 + } + ' "$f" + done < <(find "$PKG" -name '*.cs' -print0)) + + if [ -n "$HITS" ]; then + echo "::error::Unguarded post-2021.3 API usage (wrap in '#if UNITY_2023_1_OR_NEWER ... #else #endif'):" + echo "$HITS" + exit 1 + fi + + echo "Min-API lint passed: no unguarded post-2021.3 Find*ByType usage."