Skip to content

Commit 7a4a46e

Browse files
authored
feat: centralise KSU, KSUN and SUSFS hash resolution in set-op-model (#32)
Source: WildKernels/OnePlus_KernelSU_SUSFS#149
1 parent 9ce3765 commit 7a4a46e

1 file changed

Lines changed: 162 additions & 78 deletions

File tree

.github/workflows/build-kernel-release.yml

Lines changed: 162 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)