@@ -126,6 +126,9 @@ jobs:
126126 outputs :
127127 matrix : ${{ steps.set-matrix.outputs.matrix }}
128128 device_count : ${{ steps.set-matrix.outputs.count }}
129+ ksu_resolved_hash : ${{ steps.set-matrix.outputs.ksu_resolved_hash }}
130+ ksu_options_normalized : ${{ steps.set-matrix.outputs.ksu_options_normalized }}
131+ susfs_resolved_hash : ${{ steps.set-matrix.outputs.susfs_resolved_hash }}
129132 steps :
130133 - name : 📥 Checkout Code (to access configs/)
131134 uses : actions/checkout@v6
@@ -138,6 +141,9 @@ jobs:
138141 - name : 🔍 Generate build matrix
139142 id : set-matrix
140143 shell : bash
144+ env :
145+ GH_TOKEN : ${{ github.token }}
146+ GH_HTTP_TIMEOUT : 600
141147 run : |
142148 set -euo pipefail
143149 echo "::group::Matrix generation"
@@ -200,15 +206,142 @@ jobs:
200206 merged_matrix=$(jq -n --argjson devices "$filtered" --argjson ksu_list "$ksu_options_normalized" '[ $devices[] as $dev | $ksu_list[] as $ksu | ($dev + {ksu_type: $ksu.type, ksu_hash: $ksu.hash}) ]')
201207
202208 final_count=$(echo "$merged_matrix" | jq -s length)
203- wrapped=$(jq -n --argjson items "$merged_matrix" '{ include: $items }')
204209
205210 echo "✅ Found $final_count device(s) to build"
206211 echo ""
207212 echo "Selected devices:"
208213 jq -r '.[] | " - \(.model) (\(.os_version), \(.android_version)-\(.kernel_version), \(.ksu_type) - \(.ksu_hash))"' <<<"$merged_matrix"
209214
210- echo "matrix=$(jq -c . <<< "$wrapped")" >> "$GITHUB_OUTPUT"
211215 echo "count=$count" >> "$GITHUB_OUTPUT"
216+ echo "ksu_options_normalized=$ksu_options_normalized" >> "$GITHUB_OUTPUT"
217+
218+ ksu_type=$(echo "$ksu_options_normalized" | jq -r '.[0].type')
219+ ksu_ref=$(echo "$ksu_options_normalized" | jq -r '.[0].hash')
220+
221+ if [ "$ksu_type" == "KSUN" ]; then
222+ KSU_REPO_OWNER="KernelSU-Next"
223+ KSU_REPO_NAME="KernelSU-Next"
224+ else
225+ KSU_REPO_OWNER="tiann"
226+ KSU_REPO_NAME="KernelSU"
227+ fi
228+
229+ HEAD_REF="refs/heads/${ksu_ref}"
230+ TAG_REF="refs/tags/${ksu_ref}"
231+
232+ QUERY='query($owner: String!, $name: String!, $headRef: String!, $tagRef: String!, $objRef: String!) {
233+ repository(owner: $owner, name: $name) {
234+ hb: ref(qualifiedName: $headRef) { t: target { ... on Commit { o: oid } } }
235+ ht: ref(qualifiedName: $tagRef) { t: target { ... on Commit { o: oid } } }
236+ ho: object(expression: $objRef) { ... on Commit { o: oid } }
237+ }
238+ }'
239+
240+ MAX_RETRIES=3
241+ RETRY_COUNT=0
242+ RETRY_DELAY=5
243+
244+ echo "Resolving $ksu_type hash ($ksu_ref)..."
245+
246+ until [ $RETRY_COUNT -ge $MAX_RETRIES ]; do
247+ RESULT=$(gh api graphql -f query="$QUERY" -f owner="$KSU_REPO_OWNER" -f name="$KSU_REPO_NAME" -f headRef="$HEAD_REF" -f tagRef="$TAG_REF" -f objRef="$ksu_ref" 2>/dev/null)
248+ EXIT_CODE=$?
249+
250+ if [ $EXIT_CODE -eq 0 ] && [ -n "$RESULT" ]; then
251+ echo " ✅ API Success"
252+ break
253+ fi
254+
255+ RETRY_COUNT=$((RETRY_COUNT + 1))
256+ echo "::warning::API failed (Attempt $RETRY_COUNT/$MAX_RETRIES). Retrying in ${RETRY_DELAY}s..."
257+ sleep $RETRY_DELAY
258+ done
259+
260+ if [ $RETRY_COUNT -eq $MAX_RETRIES ]; then
261+ echo "::error::GitHub API unreachable. Cannot validate $ksu_ref"
262+ exit 1
263+ fi
264+
265+ resolved_sha=$(echo "$RESULT" | jq -r '.data.repository | (.hb.t.o // .ht.t.o // .ho.o // "unknown")')
266+
267+ if [ "$resolved_sha" == "unknown" ]; then
268+ echo "::error::Ref/Hash '$ksu_ref' does not exist in $KSU_REPO_OWNER/$KSU_REPO_NAME"
269+ exit 1
270+ fi
271+
272+ echo " ✅ Resolved: $ksu_type/$ksu_ref → $resolved_sha"
273+ echo "ksu_resolved_hash=$resolved_sha" >> "$GITHUB_OUTPUT"
274+
275+ # Inject ksu_resolved_hash into matrix
276+ merged_matrix=$(echo "$merged_matrix" | jq --arg resolved_sha "$resolved_sha" 'map(.ksu_resolved_hash = $resolved_sha)')
277+
278+ # SUSFS hash fetch
279+ SUSFS_REPO="https://gitlab.com/simonpunk/susfs4ksu.git"
280+ PROJECT_ID="simonpunk%2fsusfs4ksu"
281+ android_ver=$(echo "$merged_matrix" | jq -r '.[0].android_version')
282+ kernel_ver=$(echo "$merged_matrix" | jq -r '.[0].kernel_version')
283+ susfs_key="${android_ver}-${kernel_ver}"
284+
285+ declare -A default_branches=(
286+ ["android12-5.10"]="gki-android12-5.10"
287+ ["android13-5.15"]="gki-android13-5.15"
288+ ["android14-6.1"]="gki-android14-6.1"
289+ ["android15-6.6"]="gki-android15-6.6"
290+ ["android16-6.12"]="gki-android16-6.12"
291+ )
292+
293+ user_val="${{ inputs.susfs_branch_or_commit }}"
294+ default_val="${default_branches[$susfs_key]:-gki-android15-6.6}"
295+ susfs_ref="${user_val:-$default_val}"
296+
297+ susfs_enabled=$(echo "$merged_matrix" | jq -r '.[0].susfs')
298+
299+ if [ "$susfs_enabled" = "true" ]; then
300+ echo "🔍 Resolving SUSFS hash for: $susfs_key (ref: $susfs_ref)"
301+
302+ MAX_RETRIES=3
303+ RETRY_COUNT=0
304+ RETRY_DELAY=5
305+ susfs_resolved=""
306+
307+ until [ $RETRY_COUNT -ge $MAX_RETRIES ]; do
308+ # We query the commit endpoint which accepts Branch, Tag, or SHA
309+ RESULT=$(curl -s --fail \
310+ "https://gitlab.com/api/v4/projects/${PROJECT_ID}/repository/commits/${susfs_ref}")
311+ EXIT_CODE=$?
312+
313+ if [ $EXIT_CODE -eq 0 ] && [ -n "$RESULT" ]; then
314+ susfs_resolved=$(echo "$RESULT" | jq -r '.id')
315+ echo " ✅ Resolved: $susfs_key → $susfs_resolved"
316+ break
317+ fi
318+
319+ RETRY_COUNT=$((RETRY_COUNT + 1))
320+ echo "::warning::GitLab API failed (Attempt $RETRY_COUNT/$MAX_RETRIES). Retrying..."
321+ sleep $RETRY_DELAY
322+ done
323+
324+ # Final Validation
325+ if [ -z "$susfs_resolved" ] || [ "$susfs_resolved" = "null" ]; then
326+ echo "::error::Could not resolve SUSFS ref '$susfs_ref' for $susfs_key on GitLab."
327+ exit 1
328+ fi
329+ else
330+ susfs_resolved="unknown"
331+ echo "ℹ️ SUSFS disabled for this device, skipping resolution"
332+ fi
333+
334+ echo "susfs_resolved_hash=$susfs_resolved" >> "$GITHUB_OUTPUT"
335+
336+ # Inject susfs_resolved_hash into matrix
337+ merged_matrix=$(echo "$merged_matrix" | jq \
338+ --arg susfs_resolved "$susfs_resolved" \
339+ 'map(.susfs_resolved_hash = $susfs_resolved)')
340+
341+ # Recalculate wrapped with updated matrix and write output
342+ wrapped=$(jq -n --argjson items "$merged_matrix" '{ include: $items }')
343+ echo "matrix=$(jq -c . <<< "$wrapped")" >> "$GITHUB_OUTPUT"
344+
212345 echo "::endgroup::"
213346
214347 - name : Upload build matrix
@@ -221,24 +354,18 @@ jobs:
221354
222355 - name : 📊 Build plan summary
223356 run : |
224- ksu_options_raw='${{ github.event.inputs.ksu_options }}'
225- ksu_options_normalized=$(echo "$ksu_options_raw" | jq -c 'map(if .type then .type |= ascii_upcase | if .hash == null then if .type == "KSUN" then .hash = "dev" elif .type == "KSU" then .hash = "main" else .hash end else . end else error("No type found") end)' 2>&1)
226-
227- # export KSU_OPTIONS="$ksu_options_normalized"
228-
229- # cat >> $GITHUB_STEP_SUMMARY << 'EOF'
230- # ## 🎯 Build Plan
231-
232- # **Target:** `${{ inputs.op_model }}`
233- # **Devices:** ${{ steps.set-matrix.outputs.count }}
234-
235- # **Configuration:**
236- # - KSU Config: `"$KSU_OPTIONS"`
237- # - Optimization: `${{ inputs.optimize_level }}`
238- # - Clean Build/No Ccache: ${{ inputs.clean_build && '✅ Yes' || '❌ No' }}
239-
240- # **SUSFS Configuration:**
241- # EOF
357+ ksu_type="${{ fromJSON(steps.set-matrix.outputs.ksu_options_normalized)[0].type }}"
358+ ksu_ref="${{ fromJSON(steps.set-matrix.outputs.ksu_options_normalized)[0].hash }}"
359+ ksu_resolved="${{ steps.set-matrix.outputs.ksu_resolved_hash }}"
360+
361+ ksu_display=""
362+ if [ "$ksu_type" = "KSUN" ] || [ "$ksu_type" = "KSU" ]; then
363+ if [[ "$ksu_ref" =~ ^[0-9a-f]{40}$ ]]; then
364+ ksu_display+="📌 \`$ksu_type\`, \`$ksu_ref\`"
365+ else
366+ ksu_display+="🔀 \`$ksu_type\`, \`$ksu_ref\` (\`$ksu_resolved\`)"
367+ fi
368+ fi
242369
243370 {
244371 cat << 'EOF'
@@ -248,34 +375,35 @@ jobs:
248375 **Devices:** ${{ steps.set-matrix.outputs.count }}
249376
250377 **Configuration:**
251- - KSU Config: `
252378 EOF
253379
254- # Inject the shell variable
255- printf '%s' "$ksu_options_normalized"
380+ echo "- KSU Config: $ksu_display"
256381
257382 cat << 'EOF'
258- `
259383 - Optimization: ${{ inputs.optimize_level }}
260384 - Clean Build/No Ccache: ${{ inputs.clean_build && '✅ Yes' || '❌ No' }}
261385
262386 **SUSFS Configuration:**
263387 EOF
264388 } >> "$GITHUB_STEP_SUMMARY"
265389
390+ susfs_input="${{ inputs.susfs_branch_or_commit }}"
391+ susfs_resolved="${{ steps.set-matrix.outputs.susfs_resolved_hash }}"
266392 matrix_json='${{ steps.set-matrix.outputs.matrix }}'
267393 android_ver=$(echo "$matrix_json" | jq -r '.include[0].android_version')
268- kernel_ver=$(echo "$matrix_json" | jq -r '.include[0].kernel_version')
394+ kernel_ver=$(echo "$matrix_json" | jq -r '.include[0].kernel_version')
269395 key="${android_ver}-${kernel_ver}"
270396
271- if [ -z "${{ inputs.susfs_branch_or_commit }}" ]; then
272- echo "- SusFS Commit Hash: 🔄 auto (\`gki-$key\`)" >> $GITHUB_STEP_SUMMARY
397+ if [ -z "$susfs_input" ]; then
398+ echo "- $key: 🔄 auto (\`$susfs_resolved\`)" >> $GITHUB_STEP_SUMMARY
399+ elif [[ "$susfs_input" =~ ^[0-9a-f]{40}$ ]]; then
400+ echo "- $key: 📌 \`$susfs_input\`" >> $GITHUB_STEP_SUMMARY
273401 else
274- echo "- SusFS Commit Hash:: 📌 \`${{ inputs.susfs_branch_or_commit }}\` " >> $GITHUB_STEP_SUMMARY
402+ echo "- $key: 🔀 \`$susfs_input\` (\`$susfs_resolved\`) " >> $GITHUB_STEP_SUMMARY
275403 fi
276404
277405 echo "" >> $GITHUB_STEP_SUMMARY
278- echo "> **💡 Note:** Empty values auto-map to matching \`gki-androidX-Y.Z\` branches ." >> $GITHUB_STEP_SUMMARY
406+ echo "> **💡 Note:** Hashes are resolved at run time via API calls before builds start ." >> $GITHUB_STEP_SUMMARY
279407
280408 # Add OOS restriction note for android-kernel filters
281409 if [[ "${{ inputs.op_model }}" == android*-*.* ]]; then
@@ -325,50 +453,6 @@ jobs:
325453 chmod +x util_free_space.sh
326454 ./util_free_space.sh
327455
328- - name : 🔍 Resolve SUSFS branch from inputs
329- id : susfs
330- shell : bash
331- if : ${{ matrix.susfs }}
332- run : |
333- set -euo pipefail
334-
335- key="${{ matrix.android_version }}-${{ matrix.kernel_version }}"
336-
337- echo "Looking up SUSFS branch for: $key"
338-
339- # Map kernel version to input value
340- case "$key" in
341- "android12-5.10")
342- susfs_branch="${{ inputs.susfs_branch_or_commit }}"
343- ;;
344- "android13-5.15")
345- susfs_branch="${{ inputs.susfs_branch_or_commit }}"
346- ;;
347- "android14-6.1")
348- susfs_branch="${{ inputs.susfs_branch_or_commit }}"
349- ;;
350- "android15-6.6")
351- susfs_branch="${{ inputs.susfs_branch_or_commit }}"
352- ;;
353- "android16-6.12")
354- susfs_branch="${{ inputs.susfs_branch_or_commit }}"
355- ;;
356- *)
357- echo "::error::Unsupported kernel version: $key"
358- exit 1
359- ;;
360- esac
361-
362- # If empty, it will be auto-resolved to gki-* branch in the action
363- if [ -z "$susfs_branch" ]; then
364- echo "ℹ️ No custom SUSFS branch specified for $key"
365- echo " Will auto-select: gki-$key"
366- else
367- echo "✅ Using custom SUSFS branch for $key: '$susfs_branch'"
368- fi
369-
370- echo "susfs_branch=$susfs_branch" >> "$GITHUB_OUTPUT"
371-
372456 - name : Install Minimal Dependencies
373457 run : |
374458 set -euo pipefail
@@ -406,7 +490,7 @@ jobs:
406490 id : prepare_config
407491 shell : bash
408492 run : |
409- echo "config_json=$(jq -nc --argjson m '${{ toJSON(matrix) }}' '$m | del(.ksu_type, .ksu_hash)')" >> "$GITHUB_OUTPUT"
493+ echo "config_json=$(jq -nc --argjson m '${{ toJSON(matrix) }}' '$m | del(.ksu_type, .ksu_hash, .ksu_resolved_hash, .susfs_resolved_hash )')" >> "$GITHUB_OUTPUT"
410494
411495 - name : 📥 Checkout Code (to access manifests/)
412496 uses : actions/checkout@v6
@@ -423,8 +507,8 @@ jobs:
423507 with :
424508 op_config_json : ${{ steps.prepare_config.outputs.config_json }}
425509 ksu_type : ${{ matrix.ksu_type }}
426- ksu_branch_or_hash : ${{ matrix.ksu_hash }}
427- susfs_commit_hash_or_branch : ${{ steps.susfs.outputs.susfs_branch }}
510+ ksu_branch_or_hash : ${{ matrix.ksu_resolved_hash }}
511+ susfs_commit_hash_or_branch : ${{ matrix.susfs_resolved_hash }}
428512 optimize_level : ${{ inputs.optimize_level }}
429513 clean : ${{ inputs.clean_build }}
430514
@@ -438,7 +522,7 @@ jobs:
438522 echo "OS Version: ${{ matrix.os_version }}"
439523 echo "Kernel: ${{ matrix.android_version }}-${{ matrix.kernel_version }}"
440524 if [ "${{ matrix.susfs }}" = true ]; then
441- echo "SUSFS Branch : ${{ steps.susfs.outputs.susfs_branch }}"
525+ echo "SUSFS Hash : ${{ matrix.susfs_resolved_hash }}"
442526 fi
443527 echo "Status: ${{ job.status }}"
444528
@@ -490,7 +574,7 @@ jobs:
490574
491575 if [ "${{ matrix.susfs }}" = true ]; then
492576 cat >> $GITHUB_STEP_SUMMARY << EOF
493- **SUSFS Branch :** \`${{ steps.susfs.outputs.susfs_branch || format('(auto: gki-{0}-{1})', matrix.android_version, matrix.kernel_version) }}\`
577+ **SUSFS Hash :** \`${{ matrix.susfs_resolved_hash }}\`
494578 EOF
495579 fi
496580
0 commit comments