1313 analysis :
1414 name : Run Analysis
1515 runs-on : ubuntu-latest
16-
16+
1717 steps :
1818 - name : Checkout Code
1919 uses : actions/checkout@v4
2828 cache : true
2929
3030 - name : Build SFW
31+ # Building strictly from source to ensure binary integrity before execution.
3132 run : |
3233 mkdir -p bin
3334 CGO_ENABLED=0 go build -o bin/sfw ./cmd/sfw
@@ -56,21 +57,21 @@ jobs:
5657 BASE_REF=$(git merge-base origin/main HEAD)
5758 HEAD_REF="HEAD"
5859 fi
59-
60+
6061 # 2. Setup Base Worktree
6162 # We create the worktree in the workspace so it is mounted into the sandbox.
6263 WORKTREE_DIR=".sfw_base"
6364 # Clean up previous run if exists
6465 rm -rf "$WORKTREE_DIR"
6566 git worktree add --detach "$WORKTREE_DIR" "$BASE_REF"
66-
67+
6768 echo "worktree_dir=$WORKTREE_DIR" >> $GITHUB_OUTPUT
6869
6970 # 3. Pre-calculate Diff (CRITICAL HARDENING)
7071 # We run git on the host (where it works) and save the status to a file.
7172 # The sandbox will simply read this file, avoiding "dubious ownership" errors.
7273 git diff -z --name-status "$BASE_REF" "$HEAD_REF" > diff_stream.bin
73-
74+
7475 # Check for Go files to fail fast if none exist
7576 if git diff --name-only "$BASE_REF" "$HEAD_REF" | grep -q '\.go$'; then
7677 echo "has_go_files=true" >> $GITHUB_OUTPUT
@@ -80,13 +81,16 @@ jobs:
8081
8182 - name : Run Semantic Analysis (Sandboxed)
8283 uses : geomys/sandboxed-step@v1.2.0
84+ # FIX: 'env' must be a sibling to 'with', not a child.
85+ # This injects the vars into the process environment where the sandbox can see them.
86+ env :
87+ MODE : ${{ steps.mode.outputs.mode }}
88+ WORKTREE_DIR : ${{ steps.prep.outputs.worktree_dir }}
89+ HAS_GO : ${{ steps.prep.outputs.has_go_files }}
8390 with :
8491 disable-network : ' true'
85- # We pass environment variables for safety, preventing script injection
86- env :
87- MODE : ${{ steps.mode.outputs.mode }}
88- WORKTREE_DIR : ${{ steps.prep.outputs.worktree_dir }}
89- HAS_GO : ${{ steps.prep.outputs.has_go_files }}
92+ # Assuming 'run' is a valid input parameter for geomys/sandboxed-step.
93+ # If this action does not support a 'run' input, you must use 'entrypoint'.
9094 run : |
9195 set -euo pipefail
9296
@@ -156,15 +160,15 @@ jobs:
156160 echo "| \`$OLD_FILE_REF\` | Deleted | N/A |" >> $GITHUB_STEP_SUMMARY
157161 continue
158162 fi
159-
163+
160164 # Execute SFW using the local binary built in the previous step
161165 # We use '|| true' to capture exit codes without crashing the script (due to set -e)
162166 if ! OUTPUT=$(./bin/sfw diff "$OLD_FILE" "$NEW_FILE"); then
163167 echo "::error::sfw failed to process $NEW_FILE_REF"
164168 ERROR_COUNT=$((ERROR_COUNT + 1))
165169 continue
166170 fi
167-
171+
168172 # Validate JSON
169173 if ! echo "$OUTPUT" | jq -e . >/dev/null 2>&1; then
170174 echo "::error::Invalid JSON output for $NEW_FILE_REF"
@@ -175,14 +179,14 @@ jobs:
175179 # Parse Results using jq (replaces 'bc' dependency)
176180 PCT=$(echo "$OUTPUT" | jq -r '.summary.semantic_match_pct // 0')
177181 MODIFIED=$(echo "$OUTPUT" | jq -r '.summary.modified // 0')
178-
182+
179183 # Logic check using jq to avoid floating point issues in shell
180184 IS_BELOW_100=$(echo "$OUTPUT" | jq -r 'if (.summary.semantic_match_pct // 0) < 100 then "true" else "false" end')
181185
182- if [ "$IS_BELOW_100" == "true" ]; then
186+ if [ "$IS_BELOW_100" = "true" ]; then
183187 STATUS_ICON="Modified ($MODIFIED)"
184188 echo "| \`$NEW_FILE_REF\` | $STATUS_ICON | **$PCT%** |" >> $GITHUB_STEP_SUMMARY
185-
189+
186190 if [ "$MODE" == "BLOCKER" ]; then
187191 echo "::error file=$NEW_FILE_REF::Logic change detected in safe refactor! ($PCT%)"
188192 LOGIC_FAIL=1
0 commit comments