├── configs ├── oos16 │ ├── OP13.json │ ├── OP11.json │ ├── OP13S.json │ ├── OP13T.json │ ├── OP-ACE-6.json │ ├── OP-PAD-3.json │ ├── OP12.json │ ├── OP12r.json │ ├── OP13r.json │ ├── OP-ACE-3.json │ ├── OP-OPEN.json │ ├── OP-ACE-3V.json │ ├── OP-ACE-5.json │ ├── OP-NORD-4.json │ ├── OP-NORD-5.json │ ├── OP-PAD-2.json │ ├── OP-ACE-5-PRO.json │ ├── OP-PAD-2-PRO.json │ ├── OP-PAD-PRO.json │ └── OP-ACE-3-PRO.json ├── oos14 │ ├── OP11.json │ ├── OP12.json │ ├── OP11r.json │ ├── OP-PAD-PRO.json │ └── OP-ACE-3-PRO.json └── oos15 │ ├── OP11.json │ ├── OP13S.json │ ├── OP13T.json │ ├── OP-PAD-3.json │ ├── OP10t.json │ ├── OP11r.json │ ├── OP12.json │ ├── OP12r.json │ ├── OP13-PJZ.json │ ├── OP13r.json │ ├── OP-ACE-2.json │ ├── OP-ACE-3.json │ ├── OP-OPEN.json │ ├── OP10pro.json │ ├── OP13-CPH.json │ ├── OP-ACE-3V.json │ ├── OP-ACE-5.json │ ├── OP-NORD-4.json │ ├── OP-NORD-5.json │ ├── OP-PAD-2.json │ ├── OP-ACE-5-PRO.json │ ├── OP-NORD-4-CE.json │ ├── OP-PAD-2-PRO.json │ ├── OP-PAD-PRO.json │ ├── OP-ACE-2-PRO.json │ ├── OP-ACE-3-PRO.json │ └── OP-NORD-CE4-LITE.json ├── manifests ├── oos14 │ ├── oneplus_11r_u.xml │ ├── oneplus_11_u.xml │ ├── oneplus_12_u.xml │ ├── oneplus_ace3_pro_u.xml │ └── oneplus_pad_pro_u.xml ├── oos15 │ ├── oneplus_10_pro_v.xml │ ├── oneplus_ace2_v.xml │ ├── oneplus_10t_v.xml │ ├── oneplus_11r_v.xml │ ├── oneplus_11_v.xml │ ├── oneplus_ace3_v.xml │ ├── oneplus_12r_v.xml │ ├── oneplus_ace2_pro_v.xml │ ├── oneplus_nord_ce4_v.xml │ ├── oneplus_open_v.xml │ ├── oneplus_ace_3v_v.xml │ ├── oneplus_nord_4_v.xml │ ├── oneplus_nord_5_v.xml │ ├── oneplus_ace3_pro_v.xml │ ├── oneplus_pad2_v.xml │ ├── oneplus_13r_v.xml │ ├── oneplus_ace5_v.xml │ ├── oneplus_nord_ce4_lite_5g_v.xml │ ├── oneplus_pad_pro_v.xml │ ├── oneplus_12_v.xml │ ├── oneplus_pad_3_v.xml │ ├── oneplus_13_v.xml │ ├── oneplus_13s_v.xml │ ├── oneplus_13t_v.xml │ ├── oneplus_pad_2_pro_v.xml │ ├── oneplus_ace5_pro_v.xml │ └── oneplus_13_global_v.xml └── oos16 │ ├── oneplus_11_w.xml │ ├── oneplus_ace3_w.xml │ ├── oneplus_12r_w.xml │ ├── oneplus_open_w.xml │ ├── oneplus_ace_3v_w.xml │ ├── oneplus_nord_4_w.xml │ ├── oneplus_nord_5_w.xml │ ├── oneplus_pad2_w.xml │ ├── oneplus_ace5_w.xml │ ├── oneplus_pad_pro_w.xml │ ├── oneplus_13r_w.xml │ ├── oneplus_ace3_pro_w.xml │ ├── oneplus_12_w.xml │ ├── oneplus_ace_6_w.xml │ ├── oneplus_pad_3_w.xml │ ├── oneplus_13_w.xml │ ├── oneplus_13s_w.xml │ ├── oneplus_13t_w.xml │ ├── oneplus_pad_2_pro_w.xml │ └── oneplus_ace5_pro_w.xml ├── compatibility.md ├── README.md └── .github └── workflows ├── build-kernel-release.yml └── clean-up.yml /configs/oos16/OP13.json: -------------------------------------------------------------------------------- 1 | { 2 | "model": "OP13", 3 | "soc": "sun", 4 | "branch": "wild/sm8750", 5 | "manifest": "oneplus_13_w.xml", 6 | "android_version": "android15", 7 | "kernel_version": "6.6", 8 | "os_version": "OOS16", 9 | "disk_cleanup": false, 10 | "hmbird": true, 11 | "susfs": true, 12 | "bbg": true, 13 | "bbr": true, 14 | "ttl": true, 15 | "ip_set": true 16 | } 17 | -------------------------------------------------------------------------------- /configs/oos14/OP11.json: -------------------------------------------------------------------------------- 1 | { 2 | "model": "OP11", 3 | "soc": "kalama", 4 | "branch": "wild/sm8550", 5 | "manifest": "oneplus_11_u.xml", 6 | "android_version": "android13", 7 | "kernel_version": "5.15", 8 | "os_version": "OOS14", 9 | "disk_cleanup": true, 10 | "hmbird": false, 11 | "susfs": true, 12 | "bbg": true, 13 | "bbr": true, 14 | "ttl": true, 15 | "ip_set": true 16 | } 17 | -------------------------------------------------------------------------------- /configs/oos14/OP12.json: -------------------------------------------------------------------------------- 1 | { 2 | "model": "OP12", 3 | "soc": "pineapple", 4 | "branch": "wild/sm8650", 5 | "manifest": "oneplus_12_u.xml", 6 | "android_version": "android14", 7 | "kernel_version": "6.1", 8 | "os_version": "OOS14", 9 | "disk_cleanup": true, 10 | "hmbird": false, 11 | "susfs": true, 12 | "bbg": true, 13 | "bbr": true, 14 | "ttl": true, 15 | "ip_set": true 16 | } 17 | -------------------------------------------------------------------------------- /configs/oos15/OP11.json: -------------------------------------------------------------------------------- 1 | { 2 | "model": "OP11", 3 | "soc": "kalama", 4 | "branch": "wild/sm8550", 5 | "manifest": "oneplus_11_v.xml", 6 | "android_version": "android13", 7 | "kernel_version": "5.15", 8 | "os_version": "OOS15", 9 | "disk_cleanup": false, 10 | "hmbird": false, 11 | "susfs": true, 12 | "bbg": true, 13 | "bbr": true, 14 | "ttl": true, 15 | "ip_set": true 16 | } 17 | -------------------------------------------------------------------------------- /configs/oos15/OP13S.json: -------------------------------------------------------------------------------- 1 | { 2 | "model": "OP13S", 3 | "soc": "sun", 4 | "branch": "wild/sm8750", 5 | "manifest": "oneplus_13s_v.xml", 6 | "android_version": "android15", 7 | "kernel_version": "6.6", 8 | "os_version": "OOS15", 9 | "disk_cleanup": false, 10 | "hmbird": true, 11 | "susfs": true, 12 | "bbg": true, 13 | "bbr": true, 14 | "ttl": true, 15 | "ip_set": true 16 | } 17 | -------------------------------------------------------------------------------- /configs/oos15/OP13T.json: -------------------------------------------------------------------------------- 1 | { 2 | "model": "OP13T", 3 | "soc": "sun", 4 | "branch": "wild/sm8750", 5 | "manifest": "oneplus_13t_v.xml", 6 | "android_version": "android15", 7 | "kernel_version": "6.6", 8 | "os_version": "OOS15", 9 | "disk_cleanup": false, 10 | "hmbird": true, 11 | "susfs": true, 12 | "bbg": true, 13 | "bbr": true, 14 | "ttl": true, 15 | "ip_set": true 16 | } 17 | -------------------------------------------------------------------------------- /configs/oos16/OP11.json: -------------------------------------------------------------------------------- 1 | { 2 | "model": "OP11", 3 | "soc": "kalama", 4 | "branch": "wild/sm8550", 5 | "manifest": "oneplus_11_w.xml", 6 | "android_version": "android13", 7 | "kernel_version": "5.15", 8 | "os_version": "OOS16", 9 | "disk_cleanup": false, 10 | "hmbird": false, 11 | "susfs": true, 12 | "bbg": true, 13 | "bbr": true, 14 | "ttl": true, 15 | "ip_set": true 16 | } 17 | -------------------------------------------------------------------------------- /configs/oos16/OP13S.json: -------------------------------------------------------------------------------- 1 | { 2 | "model": "OP13S", 3 | "soc": "sun", 4 | "branch": "wild/sm8750", 5 | "manifest": "oneplus_13s_w.xml", 6 | "android_version": "android15", 7 | "kernel_version": "6.6", 8 | "os_version": "OOS16", 9 | "disk_cleanup": false, 10 | "hmbird": true, 11 | "susfs": true, 12 | "bbg": true, 13 | "bbr": true, 14 | "ttl": true, 15 | "ip_set": true 16 | } 17 | -------------------------------------------------------------------------------- /configs/oos16/OP13T.json: -------------------------------------------------------------------------------- 1 | { 2 | "model": "OP13T", 3 | "soc": "sun", 4 | "branch": "wild/sm8750", 5 | "manifest": "oneplus_13t_w.xml", 6 | "android_version": "android15", 7 | "kernel_version": "6.6", 8 | "os_version": "OOS16", 9 | "disk_cleanup": false, 10 | "hmbird": true, 11 | "susfs": true, 12 | "bbg": true, 13 | "bbr": true, 14 | "ttl": true, 15 | "ip_set": true 16 | } 17 | -------------------------------------------------------------------------------- /configs/oos14/OP11r.json: -------------------------------------------------------------------------------- 1 | { 2 | "model": "OP11r", 3 | "soc": "waipio", 4 | "branch": "wild/sm8475", 5 | "manifest": "oneplus_11r_u.xml", 6 | "android_version": "android12", 7 | "kernel_version": "5.10", 8 | "os_version": "OOS14", 9 | "disk_cleanup": true, 10 | "hmbird": false, 11 | "susfs": true, 12 | "bbg": true, 13 | "bbr": true, 14 | "ttl": true, 15 | "ip_set": true 16 | } 17 | -------------------------------------------------------------------------------- /configs/oos15/OP-PAD-3.json: -------------------------------------------------------------------------------- 1 | { 2 | "model": "OP-PAD-3", 3 | "soc": "sun", 4 | "branch": "wild/sm8750", 5 | "manifest": "oneplus_pad_3_v.xml", 6 | "android_version": "android15", 7 | "kernel_version": "6.6", 8 | "os_version": "OOS15", 9 | "disk_cleanup": false, 10 | "hmbird": true, 11 | "susfs": true, 12 | "bbg": true, 13 | "bbr": true, 14 | "ttl": true, 15 | "ip_set": true 16 | } 17 | -------------------------------------------------------------------------------- /configs/oos15/OP10t.json: -------------------------------------------------------------------------------- 1 | { 2 | "model": "OP10t", 3 | "soc": "waipio", 4 | "branch": "wild/sm8475", 5 | "manifest": "oneplus_10t_v.xml", 6 | "android_version": "android12", 7 | "kernel_version": "5.10", 8 | "os_version": "OOS15", 9 | "disk_cleanup": false, 10 | "hmbird": false, 11 | "susfs": true, 12 | "bbg": true, 13 | "bbr": true, 14 | "ttl": true, 15 | "ip_set": true 16 | } 17 | -------------------------------------------------------------------------------- /configs/oos15/OP11r.json: -------------------------------------------------------------------------------- 1 | { 2 | "model": "OP11r", 3 | "soc": "waipio", 4 | "branch": "wild/sm8475", 5 | "manifest": "oneplus_11r_v.xml", 6 | "android_version": "android12", 7 | "kernel_version": "5.10", 8 | "os_version": "OOS15", 9 | "disk_cleanup": false, 10 | "hmbird": false, 11 | "susfs": true, 12 | "bbg": true, 13 | "bbr": true, 14 | "ttl": true, 15 | "ip_set": true 16 | } 17 | -------------------------------------------------------------------------------- /configs/oos15/OP12.json: -------------------------------------------------------------------------------- 1 | { 2 | "model": "OP12", 3 | "soc": "pineapple", 4 | "branch": "wild/sm8650", 5 | "manifest": "oneplus_12_v.xml", 6 | "android_version": "android14", 7 | "kernel_version": "6.1", 8 | "os_version": "OOS15", 9 | "disk_cleanup": false, 10 | "hmbird": false, 11 | "susfs": true, 12 | "bbg": true, 13 | "bbr": true, 14 | "ttl": true, 15 | "ip_set": true 16 | } 17 | -------------------------------------------------------------------------------- /configs/oos15/OP12r.json: -------------------------------------------------------------------------------- 1 | { 2 | "model": "OP12r", 3 | "soc": "kalama", 4 | "branch": "wild/sm8550", 5 | "manifest": "oneplus_12r_v.xml", 6 | "android_version": "android13", 7 | "kernel_version": "5.15", 8 | "os_version": "OOS15", 9 | "disk_cleanup": false, 10 | "hmbird": false, 11 | "susfs": true, 12 | "bbg": true, 13 | "bbr": true, 14 | "ttl": true, 15 | "ip_set": true 16 | } 17 | -------------------------------------------------------------------------------- /configs/oos15/OP13-PJZ.json: -------------------------------------------------------------------------------- 1 | { 2 | "model": "OP13-PJZ", 3 | "soc": "sun", 4 | "branch": "wild/sm8750", 5 | "manifest": "oneplus_13_v.xml", 6 | "android_version": "android15", 7 | "kernel_version": "6.6", 8 | "os_version": "OOS15", 9 | "disk_cleanup": false, 10 | "hmbird": true, 11 | "susfs": true, 12 | "bbg": true, 13 | "bbr": true, 14 | "ttl": true, 15 | "ip_set": true 16 | } 17 | -------------------------------------------------------------------------------- /configs/oos15/OP13r.json: -------------------------------------------------------------------------------- 1 | { 2 | "model": "OP13r", 3 | "soc": "pineapple", 4 | "branch": "wild/sm8650", 5 | "manifest": "oneplus_13r_v.xml", 6 | "android_version": "android14", 7 | "kernel_version": "6.1", 8 | "os_version": "OOS15", 9 | "disk_cleanup": false, 10 | "hmbird": false, 11 | "susfs": true, 12 | "bbg": true, 13 | "bbr": true, 14 | "ttl": true, 15 | "ip_set": true 16 | } 17 | -------------------------------------------------------------------------------- /configs/oos16/OP-ACE-6.json: -------------------------------------------------------------------------------- 1 | { 2 | "model": "OP-ACE-6", 3 | "soc": "sun", 4 | "branch": "wild/sm8750", 5 | "manifest": "oneplus_ace_6_w.xml", 6 | "android_version": "android15", 7 | "kernel_version": "6.6", 8 | "os_version": "OOS16", 9 | "disk_cleanup": false, 10 | "hmbird": true, 11 | "susfs": true, 12 | "bbg": true, 13 | "bbr": true, 14 | "ttl": true, 15 | "ip_set": true 16 | } 17 | -------------------------------------------------------------------------------- /configs/oos16/OP-PAD-3.json: -------------------------------------------------------------------------------- 1 | { 2 | "model": "OP-PAD-3", 3 | "soc": "sun", 4 | "branch": "wild/sm8750", 5 | "manifest": "oneplus_pad_3_w.xml", 6 | "android_version": "android15", 7 | "kernel_version": "6.6", 8 | "os_version": "OOS16", 9 | "disk_cleanup": false, 10 | "hmbird": true, 11 | "susfs": true, 12 | "bbg": true, 13 | "bbr": true, 14 | "ttl": true, 15 | "ip_set": true 16 | } 17 | -------------------------------------------------------------------------------- /configs/oos16/OP12.json: -------------------------------------------------------------------------------- 1 | { 2 | "model": "OP12", 3 | "soc": "pineapple", 4 | "branch": "wild/sm8650", 5 | "manifest": "oneplus_12_w.xml", 6 | "android_version": "android14", 7 | "kernel_version": "6.1", 8 | "os_version": "OOS16", 9 | "disk_cleanup": false, 10 | "hmbird": false, 11 | "susfs": true, 12 | "bbg": true, 13 | "bbr": true, 14 | "ttl": true, 15 | "ip_set": true 16 | } 17 | -------------------------------------------------------------------------------- /configs/oos16/OP12r.json: -------------------------------------------------------------------------------- 1 | { 2 | "model": "OP12r", 3 | "soc": "kalama", 4 | "branch": "wild/sm8550", 5 | "manifest": "oneplus_12r_w.xml", 6 | "android_version": "android13", 7 | "kernel_version": "5.15", 8 | "os_version": "OOS16", 9 | "disk_cleanup": false, 10 | "hmbird": false, 11 | "susfs": true, 12 | "bbg": true, 13 | "bbr": true, 14 | "ttl": true, 15 | "ip_set": true 16 | } 17 | -------------------------------------------------------------------------------- /configs/oos16/OP13r.json: -------------------------------------------------------------------------------- 1 | { 2 | "model": "OP13r", 3 | "soc": "pineapple", 4 | "branch": "wild/sm8650", 5 | "manifest": "oneplus_13r_w.xml", 6 | "android_version": "android14", 7 | "kernel_version": "6.1", 8 | "os_version": "OOS16", 9 | "disk_cleanup": false, 10 | "hmbird": false, 11 | "susfs": true, 12 | "bbg": true, 13 | "bbr": true, 14 | "ttl": true, 15 | "ip_set": true 16 | } 17 | -------------------------------------------------------------------------------- /configs/oos15/OP-ACE-2.json: -------------------------------------------------------------------------------- 1 | { 2 | "model": "OP-ACE-2", 3 | "soc": "waipio", 4 | "branch": "wild/sm8475", 5 | "manifest": "oneplus_ace2_v.xml", 6 | "android_version": "android12", 7 | "kernel_version": "5.10", 8 | "os_version": "OOS15", 9 | "disk_cleanup": false, 10 | "hmbird": false, 11 | "susfs": true, 12 | "bbg": true, 13 | "bbr": true, 14 | "ttl": true, 15 | "ip_set": true 16 | } 17 | -------------------------------------------------------------------------------- /configs/oos15/OP-ACE-3.json: -------------------------------------------------------------------------------- 1 | { 2 | "model": "OP-ACE-3", 3 | "soc": "kalama", 4 | "branch": "wild/sm8550", 5 | "manifest": "oneplus_ace3_v.xml", 6 | "android_version": "android13", 7 | "kernel_version": "5.15", 8 | "os_version": "OOS15", 9 | "disk_cleanup": false, 10 | "hmbird": false, 11 | "susfs": true, 12 | "bbg": true, 13 | "bbr": true, 14 | "ttl": true, 15 | "ip_set": true 16 | } 17 | -------------------------------------------------------------------------------- /configs/oos15/OP-OPEN.json: -------------------------------------------------------------------------------- 1 | { 2 | "model": "OP-OPEN", 3 | "soc": "kalama", 4 | "branch": "wild/sm8550", 5 | "manifest": "oneplus_open_v.xml", 6 | "android_version": "android13", 7 | "kernel_version": "5.15", 8 | "os_version": "OOS15", 9 | "disk_cleanup": false, 10 | "hmbird": false, 11 | "susfs": true, 12 | "bbg": true, 13 | "bbr": true, 14 | "ttl": true, 15 | "ip_set": true 16 | } 17 | -------------------------------------------------------------------------------- /configs/oos15/OP10pro.json: -------------------------------------------------------------------------------- 1 | { 2 | "model": "OP10pro", 3 | "soc": "waipio", 4 | "branch": "wild/sm8450", 5 | "manifest": "oneplus_10_pro_v.xml", 6 | "android_version": "android12", 7 | "kernel_version": "5.10", 8 | "os_version": "OOS15", 9 | "disk_cleanup": false, 10 | "hmbird": false, 11 | "susfs": true, 12 | "bbg": true, 13 | "bbr": true, 14 | "ttl": true, 15 | "ip_set": true 16 | } 17 | -------------------------------------------------------------------------------- /configs/oos15/OP13-CPH.json: -------------------------------------------------------------------------------- 1 | { 2 | "model": "OP13-CPH", 3 | "soc": "sun", 4 | "branch": "wild/sm8750", 5 | "manifest": "oneplus_13_global_v.xml", 6 | "android_version": "android15", 7 | "kernel_version": "6.6", 8 | "os_version": "OOS15", 9 | "disk_cleanup": false, 10 | "hmbird": true, 11 | "susfs": true, 12 | "bbg": true, 13 | "bbr": true, 14 | "ttl": true, 15 | "ip_set": true 16 | } 17 | -------------------------------------------------------------------------------- /configs/oos16/OP-ACE-3.json: -------------------------------------------------------------------------------- 1 | { 2 | "model": "OP-ACE-3", 3 | "soc": "kalama", 4 | "branch": "wild/sm8550", 5 | "manifest": "oneplus_ace3_w.xml", 6 | "android_version": "android13", 7 | "kernel_version": "5.15", 8 | "os_version": "OOS16", 9 | "disk_cleanup": false, 10 | "hmbird": false, 11 | "susfs": true, 12 | "bbg": true, 13 | "bbr": true, 14 | "ttl": true, 15 | "ip_set": true 16 | } 17 | -------------------------------------------------------------------------------- /configs/oos16/OP-OPEN.json: -------------------------------------------------------------------------------- 1 | { 2 | "model": "OP-OPEN", 3 | "soc": "kalama", 4 | "branch": "wild/sm8550", 5 | "manifest": "oneplus_open_w.xml", 6 | "android_version": "android13", 7 | "kernel_version": "5.15", 8 | "os_version": "OOS16", 9 | "disk_cleanup": false, 10 | "hmbird": false, 11 | "susfs": true, 12 | "bbg": true, 13 | "bbr": true, 14 | "ttl": true, 15 | "ip_set": true 16 | } 17 | -------------------------------------------------------------------------------- /configs/oos15/OP-ACE-3V.json: -------------------------------------------------------------------------------- 1 | { 2 | "model": "OP-ACE-3V", 3 | "soc": "pineapple", 4 | "branch": "wild/sm7675", 5 | "manifest": "oneplus_ace_3v_v.xml", 6 | "android_version": "android14", 7 | "kernel_version": "6.1", 8 | "os_version": "OOS15", 9 | "disk_cleanup": false, 10 | "hmbird": false, 11 | "susfs": true, 12 | "bbg": true, 13 | "bbr": true, 14 | "ttl": true, 15 | "ip_set": true 16 | } 17 | -------------------------------------------------------------------------------- /configs/oos15/OP-ACE-5.json: -------------------------------------------------------------------------------- 1 | { 2 | "model": "OP-ACE-5", 3 | "soc": "pineapple", 4 | "branch": "wild/sm8650", 5 | "manifest": "oneplus_ace5_v.xml", 6 | "android_version": "android14", 7 | "kernel_version": "6.1", 8 | "os_version": "OOS15", 9 | "disk_cleanup": false, 10 | "hmbird": false, 11 | "susfs": true, 12 | "bbg": true, 13 | "bbr": true, 14 | "ttl": true, 15 | "ip_set": true 16 | } 17 | -------------------------------------------------------------------------------- /configs/oos15/OP-NORD-4.json: -------------------------------------------------------------------------------- 1 | { 2 | "model": "OP-NORD-4", 3 | "soc": "pineapple", 4 | "branch": "wild/sm7675", 5 | "manifest": "oneplus_nord_4_v.xml", 6 | "android_version": "android14", 7 | "kernel_version": "6.1", 8 | "os_version": "OOS15", 9 | "disk_cleanup": false, 10 | "hmbird": false, 11 | "susfs": true, 12 | "bbg": true, 13 | "bbr": true, 14 | "ttl": true, 15 | "ip_set": true 16 | } 17 | -------------------------------------------------------------------------------- /configs/oos15/OP-NORD-5.json: -------------------------------------------------------------------------------- 1 | { 2 | "model": "OP-NORD-5", 3 | "soc": "cliffs", 4 | "branch": "wild/sm8635", 5 | "manifest": "oneplus_nord_5_v.xml", 6 | "android_version": "android14", 7 | "kernel_version": "6.1", 8 | "os_version": "OOS15", 9 | "disk_cleanup": false, 10 | "hmbird": false, 11 | "susfs": true, 12 | "bbg": true, 13 | "bbr": true, 14 | "ttl": true, 15 | "ip_set": true 16 | } 17 | -------------------------------------------------------------------------------- /configs/oos15/OP-PAD-2.json: -------------------------------------------------------------------------------- 1 | { 2 | "model": "OP-PAD-2", 3 | "soc": "pineapple", 4 | "branch": "wild/sm8650", 5 | "manifest": "oneplus_pad2_v.xml", 6 | "android_version": "android14", 7 | "kernel_version": "6.1", 8 | "os_version": "OOS15", 9 | "disk_cleanup": false, 10 | "hmbird": false, 11 | "susfs": true, 12 | "bbg": true, 13 | "bbr": true, 14 | "ttl": true, 15 | "ip_set": true 16 | } 17 | -------------------------------------------------------------------------------- /configs/oos16/OP-ACE-3V.json: -------------------------------------------------------------------------------- 1 | { 2 | "model": "OP-ACE-3V", 3 | "soc": "pineapple", 4 | "branch": "wild/sm7675", 5 | "manifest": "oneplus_ace_3v_w.xml", 6 | "android_version": "android14", 7 | "kernel_version": "6.1", 8 | "os_version": "OOS16", 9 | "disk_cleanup": false, 10 | "hmbird": false, 11 | "susfs": true, 12 | "bbg": true, 13 | "bbr": true, 14 | "ttl": true, 15 | "ip_set": true 16 | } 17 | -------------------------------------------------------------------------------- /configs/oos16/OP-ACE-5.json: -------------------------------------------------------------------------------- 1 | { 2 | "model": "OP-ACE-5", 3 | "soc": "pineapple", 4 | "branch": "wild/sm8650", 5 | "manifest": "oneplus_ace5_w.xml", 6 | "android_version": "android14", 7 | "kernel_version": "6.1", 8 | "os_version": "OOS16", 9 | "disk_cleanup": false, 10 | "hmbird": false, 11 | "susfs": true, 12 | "bbg": true, 13 | "bbr": true, 14 | "ttl": true, 15 | "ip_set": true 16 | } 17 | -------------------------------------------------------------------------------- /configs/oos16/OP-NORD-4.json: -------------------------------------------------------------------------------- 1 | { 2 | "model": "OP-NORD-4", 3 | "soc": "pineapple", 4 | "branch": "wild/sm7675", 5 | "manifest": "oneplus_nord_4_w.xml", 6 | "android_version": "android14", 7 | "kernel_version": "6.1", 8 | "os_version": "OOS16", 9 | "disk_cleanup": false, 10 | "hmbird": false, 11 | "susfs": true, 12 | "bbg": true, 13 | "bbr": true, 14 | "ttl": true, 15 | "ip_set": true 16 | } 17 | -------------------------------------------------------------------------------- /configs/oos16/OP-NORD-5.json: -------------------------------------------------------------------------------- 1 | { 2 | "model": "OP-NORD-5", 3 | "soc": "cliffs", 4 | "branch": "wild/sm8635", 5 | "manifest": "oneplus_nord_5_w.xml", 6 | "android_version": "android14", 7 | "kernel_version": "6.1", 8 | "os_version": "OOS16", 9 | "disk_cleanup": false, 10 | "hmbird": false, 11 | "susfs": true, 12 | "bbg": true, 13 | "bbr": true, 14 | "ttl": true, 15 | "ip_set": true 16 | } 17 | -------------------------------------------------------------------------------- /configs/oos16/OP-PAD-2.json: -------------------------------------------------------------------------------- 1 | { 2 | "model": "OP-PAD-2", 3 | "soc": "pineapple", 4 | "branch": "wild/sm8650", 5 | "manifest": "oneplus_pad2_w.xml", 6 | "android_version": "android14", 7 | "kernel_version": "6.1", 8 | "os_version": "OOS16", 9 | "disk_cleanup": false, 10 | "hmbird": false, 11 | "susfs": true, 12 | "bbg": true, 13 | "bbr": true, 14 | "ttl": true, 15 | "ip_set": true 16 | } 17 | -------------------------------------------------------------------------------- /configs/oos14/OP-PAD-PRO.json: -------------------------------------------------------------------------------- 1 | { 2 | "model": "OP-PAD-PRO", 3 | "soc": "pineapple", 4 | "branch": "wild/sm8650", 5 | "manifest": "oneplus_pad_pro_u.xml", 6 | "android_version": "android14", 7 | "kernel_version": "6.1", 8 | "os_version": "OOS14", 9 | "disk_cleanup": true, 10 | "hmbird": false, 11 | "susfs": true, 12 | "bbg": true, 13 | "bbr": true, 14 | "ttl": true, 15 | "ip_set": true 16 | } 17 | -------------------------------------------------------------------------------- /configs/oos15/OP-ACE-5-PRO.json: -------------------------------------------------------------------------------- 1 | { 2 | "model": "OP-ACE-5-PRO", 3 | "soc": "sun", 4 | "branch": "wild/sm8750", 5 | "manifest": "oneplus_ace5_pro_v.xml", 6 | "android_version": "android15", 7 | "kernel_version": "6.6", 8 | "os_version": "OOS15", 9 | "disk_cleanup": false, 10 | "hmbird": true, 11 | "susfs": true, 12 | "bbg": true, 13 | "bbr": true, 14 | "ttl": true, 15 | "ip_set": true 16 | } 17 | -------------------------------------------------------------------------------- /configs/oos15/OP-NORD-4-CE.json: -------------------------------------------------------------------------------- 1 | { 2 | "model": "OP-NORD-4-CE", 3 | "soc": "crow", 4 | "branch": "wild/sm7550", 5 | "manifest": "oneplus_nord_ce4_v.xml", 6 | "android_version": "android13", 7 | "kernel_version": "5.15", 8 | "os_version": "OOS15", 9 | "disk_cleanup": false, 10 | "hmbird": false, 11 | "susfs": true, 12 | "bbg": true, 13 | "bbr": true, 14 | "ttl": true, 15 | "ip_set": true 16 | } 17 | -------------------------------------------------------------------------------- /configs/oos15/OP-PAD-2-PRO.json: -------------------------------------------------------------------------------- 1 | { 2 | "model": "OP-PAD-2-PRO", 3 | "soc": "sun", 4 | "branch": "wild/sm8750", 5 | "manifest": "oneplus_pad_2_pro_v.xml", 6 | "android_version": "android15", 7 | "kernel_version": "6.6", 8 | "os_version": "OOS15", 9 | "disk_cleanup": false, 10 | "hmbird": true, 11 | "susfs": true, 12 | "bbg": true, 13 | "bbr": true, 14 | "ttl": true, 15 | "ip_set": true 16 | } 17 | -------------------------------------------------------------------------------- /configs/oos15/OP-PAD-PRO.json: -------------------------------------------------------------------------------- 1 | { 2 | "model": "OP-PAD-PRO", 3 | "soc": "pineapple", 4 | "branch": "wild/sm8650", 5 | "manifest": "oneplus_pad_pro_v.xml", 6 | "android_version": "android14", 7 | "kernel_version": "6.1", 8 | "os_version": "OOS15", 9 | "disk_cleanup": false, 10 | "hmbird": false, 11 | "susfs": true, 12 | "bbg": true, 13 | "bbr": true, 14 | "ttl": true, 15 | "ip_set": true 16 | } 17 | -------------------------------------------------------------------------------- /configs/oos16/OP-ACE-5-PRO.json: -------------------------------------------------------------------------------- 1 | { 2 | "model": "OP-ACE-5-PRO", 3 | "soc": "sun", 4 | "branch": "wild/sm8750", 5 | "manifest": "oneplus_ace5_pro_w.xml", 6 | "android_version": "android15", 7 | "kernel_version": "6.6", 8 | "os_version": "OOS16", 9 | "disk_cleanup": false, 10 | "hmbird": true, 11 | "susfs": true, 12 | "bbg": true, 13 | "bbr": true, 14 | "ttl": true, 15 | "ip_set": true 16 | } 17 | -------------------------------------------------------------------------------- /configs/oos16/OP-PAD-2-PRO.json: -------------------------------------------------------------------------------- 1 | { 2 | "model": "OP-PAD-2-PRO", 3 | "soc": "sun", 4 | "branch": "wild/sm8750", 5 | "manifest": "oneplus_pad_2_pro_w.xml", 6 | "android_version": "android15", 7 | "kernel_version": "6.6", 8 | "os_version": "OOS16", 9 | "disk_cleanup": false, 10 | "hmbird": true, 11 | "susfs": true, 12 | "bbg": true, 13 | "bbr": true, 14 | "ttl": true, 15 | "ip_set": true 16 | } 17 | -------------------------------------------------------------------------------- /configs/oos16/OP-PAD-PRO.json: -------------------------------------------------------------------------------- 1 | { 2 | "model": "OP-PAD-PRO", 3 | "soc": "pineapple", 4 | "branch": "wild/sm8650", 5 | "manifest": "oneplus_pad_pro_w.xml", 6 | "android_version": "android14", 7 | "kernel_version": "6.1", 8 | "os_version": "OOS16", 9 | "disk_cleanup": false, 10 | "hmbird": false, 11 | "susfs": true, 12 | "bbg": true, 13 | "bbr": true, 14 | "ttl": true, 15 | "ip_set": true 16 | } 17 | -------------------------------------------------------------------------------- /configs/oos14/OP-ACE-3-PRO.json: -------------------------------------------------------------------------------- 1 | { 2 | "model": "OP-ACE-3-PRO", 3 | "soc": "pineapple", 4 | "branch": "wild/sm8650", 5 | "manifest": "oneplus_ace3_pro_u.xml", 6 | "android_version": "android14", 7 | "kernel_version": "6.1", 8 | "os_version": "OOS14", 9 | "disk_cleanup": true, 10 | "hmbird": false, 11 | "susfs": true, 12 | "bbg": true, 13 | "bbr": true, 14 | "ttl": true, 15 | "ip_set": true 16 | } 17 | -------------------------------------------------------------------------------- /configs/oos15/OP-ACE-2-PRO.json: -------------------------------------------------------------------------------- 1 | { 2 | "model": "OP-ACE-2-PRO", 3 | "soc": "kalama", 4 | "branch": "wild/sm8550", 5 | "manifest": "oneplus_ace2_pro_v.xml", 6 | "android_version": "android13", 7 | "kernel_version": "5.15", 8 | "os_version": "OOS15", 9 | "disk_cleanup": false, 10 | "hmbird": false, 11 | "susfs": true, 12 | "bbg": true, 13 | "bbr": true, 14 | "ttl": true, 15 | "ip_set": true 16 | } 17 | -------------------------------------------------------------------------------- /configs/oos15/OP-ACE-3-PRO.json: -------------------------------------------------------------------------------- 1 | { 2 | "model": "OP-ACE-3-PRO", 3 | "soc": "pineapple", 4 | "branch": "wild/sm8650", 5 | "manifest": "oneplus_ace3_pro_v.xml", 6 | "android_version": "android14", 7 | "kernel_version": "6.1", 8 | "os_version": "OOS15", 9 | "disk_cleanup": false, 10 | "hmbird": false, 11 | "susfs": true, 12 | "bbg": true, 13 | "bbr": true, 14 | "ttl": true, 15 | "ip_set": true 16 | } 17 | -------------------------------------------------------------------------------- /configs/oos16/OP-ACE-3-PRO.json: -------------------------------------------------------------------------------- 1 | { 2 | "model": "OP-ACE-3-PRO", 3 | "soc": "pineapple", 4 | "branch": "wild/sm8650", 5 | "manifest": "oneplus_ace3_pro_w.xml", 6 | "android_version": "android14", 7 | "kernel_version": "6.1", 8 | "os_version": "OOS16", 9 | "disk_cleanup": false, 10 | "hmbird": false, 11 | "susfs": true, 12 | "bbg": true, 13 | "bbr": true, 14 | "ttl": true, 15 | "ip_set": true 16 | } 17 | -------------------------------------------------------------------------------- /configs/oos15/OP-NORD-CE4-LITE.json: -------------------------------------------------------------------------------- 1 | { 2 | "model": "OP-NORD-CE4-LITE", 3 | "soc": "blair", 4 | "branch": "wild/sm6375", 5 | "manifest": "oneplus_nord_ce4_lite_5g_v.xml", 6 | "android_version": "android14", 7 | "kernel_version": "6.1", 8 | "os_version": "OOS15", 9 | "disk_cleanup": false, 10 | "hmbird": false, 11 | "susfs": true, 12 | "bbg": true, 13 | "bbr": true, 14 | "ttl": true, 15 | "ip_set": true 16 | } 17 | -------------------------------------------------------------------------------- /manifests/oos14/oneplus_11r_u.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /manifests/oos14/oneplus_11_u.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /manifests/oos14/oneplus_12_u.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /manifests/oos14/oneplus_ace3_pro_u.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /manifests/oos14/oneplus_pad_pro_u.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /manifests/oos15/oneplus_10_pro_v.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /manifests/oos15/oneplus_ace2_v.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /manifests/oos15/oneplus_10t_v.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /manifests/oos15/oneplus_11r_v.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /manifests/oos15/oneplus_11_v.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /manifests/oos15/oneplus_ace3_v.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /manifests/oos16/oneplus_11_w.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /manifests/oos16/oneplus_ace3_w.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /manifests/oos15/oneplus_12r_v.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /manifests/oos15/oneplus_ace2_pro_v.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /manifests/oos15/oneplus_nord_ce4_v.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /manifests/oos15/oneplus_open_v.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /manifests/oos16/oneplus_12r_w.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /manifests/oos16/oneplus_open_w.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /manifests/oos15/oneplus_ace_3v_v.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /manifests/oos15/oneplus_nord_4_v.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /manifests/oos15/oneplus_nord_5_v.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /manifests/oos16/oneplus_ace_3v_w.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /manifests/oos16/oneplus_nord_4_w.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /manifests/oos16/oneplus_nord_5_w.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /manifests/oos16/oneplus_pad2_w.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /manifests/oos16/oneplus_ace5_w.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /manifests/oos15/oneplus_ace3_pro_v.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /manifests/oos15/oneplus_pad2_v.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /manifests/oos16/oneplus_pad_pro_w.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /manifests/oos15/oneplus_13r_v.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /manifests/oos16/oneplus_13r_w.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /manifests/oos16/oneplus_ace3_pro_w.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /manifests/oos15/oneplus_ace5_v.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /manifests/oos15/oneplus_nord_ce4_lite_5g_v.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /manifests/oos15/oneplus_pad_pro_v.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /manifests/oos15/oneplus_12_v.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /manifests/oos16/oneplus_12_w.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /manifests/oos15/oneplus_pad_3_v.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /manifests/oos16/oneplus_ace_6_w.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /manifests/oos16/oneplus_pad_3_w.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /manifests/oos15/oneplus_13_v.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /manifests/oos15/oneplus_13s_v.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /manifests/oos16/oneplus_13_w.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /manifests/oos15/oneplus_13t_v.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /manifests/oos15/oneplus_pad_2_pro_v.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /manifests/oos16/oneplus_13s_w.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /manifests/oos16/oneplus_13t_w.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /manifests/oos16/oneplus_pad_2_pro_w.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /manifests/oos15/oneplus_ace5_pro_v.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /manifests/oos16/oneplus_ace5_pro_w.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /manifests/oos15/oneplus_13_global_v.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /compatibility.md: -------------------------------------------------------------------------------- 1 | # Compatibility of OnePlus Kernels 2 | ## 1. OnePlus Devices 3 | 4 | 5 | 6 | 7 | 8 | 9 |
:warning: All the Kernels are built on OnePlus Official Source and are expected to work only on Stock roms!!!
10 | 11 | - Currently All the kernels are built from Android 15 Manifest. 12 | - Do not use the zips after Major Android OTA (a15 -> a16) unless its verified in Wild_Kernels Telegram group or other sources like XDA. 13 | 14 | ## 2. Non-OnePlus Devices 15 | ### List of verified devices 16 | 17 | 18 | 19 | 20 | 21 |
:warning: We expect all users who wants to test OnePlus Kernels on Non-OnePlus Phones to first disable dm-verity and verification using fastboot or other means.
22 | 23 | - If your device is not in list, please select the device which is most similar and matches the kernel version (androidXX-YY.ZZ.AAA). AAA must be atleast same or greater. XX-YY.ZZ must match exactly. More Information on this can be read @KernelSU.org. 24 | - Thanks to our community users at Wild_Kernels for helping us compile the list. 25 | - We request more users come forward help us keep the list updated. 26 | - I'm sure more devices from other brands are also supported. 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 |
Device Name Working Kernel Device Name Current Kernel Version
Poco X7 Pro OnePlus 13
OnePlus Ace 5 Pro
android15-6.6.30
android15-6.6.30
Realme GT Neo 5SE
Realme GT Neo 5
OnePlus 10T
OnePlus 10 Pro
OnePlus Ace 2
OnePlus 11r (Partially)
android12-5.10.209
android12-5.10.209
android12-5.10.209
android12-5.10.209
Realme GT 5 OnePlus 11 android13-5.15.149
Realme GT Neo 6SE
Realme GT Neo 6T
OnePlus Nord 4 android14-6.1.75
Realme GT 2 Pro OnePlus 10 Pro android12-5.10.209
59 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Wild Kernels for Android 2 | 3 | ## Your warranty is no longer valid! 4 | 5 | I am **not responsible** for bricked devices, damaged hardware, or any issues that arise from using this kernel. 6 | 7 | **Please** do thorough research and fully understand the features included in this kernel before flashing it! 8 | 9 | By flashing this kernel, **YOU** are choosing to make these modifications. If something goes wrong, **do not blame me**! 10 | 11 | --- 12 | 13 | ### Proceed at your own risk! 14 | 15 | 16 | 17 | 18 | 19 | 20 |
:warning: Verify Compatibility of kernels before flashing.
21 | 22 | --- 23 | 24 | # Kernels: 25 | 26 | [GKI](https://github.com/WildKernels/GKI_KernelSU_SUSFS) 27 | [Sultan](https://github.com/WildKernels/Sultan_KernelSU_SUSFS) 28 | [OnePlus](https://github.com/WildKernels/OnePlus_KernelSU_SUSFS) 29 | [Legacy Pixels](https://github.com/WildKernels/Pixel_KernelSU_SUSFS) 30 | 31 | --- 32 | 33 | # Other Links: 34 | 35 | [Kernel Patches](https://github.com/WildKernels/kernel_patches) 36 | [Old Build Scripts](https://github.com/TheWildJames/kernel_build_scripts) 37 | [Kernel Flasher - fatalcoder524 fork](https://github.com/fatalcoder524/KernelFlasher) 38 | [Horizon Kernel Flasher](https://github.com/libxzr/HorizonKernelFlasher) 39 | 40 | --- 41 | 42 | # Installation instructions: 43 | 44 | Follow the steps for GKI: 45 | [Installation](https://kernelsu.org/guide/installation.html) 46 | 47 | To get boot.img format: 48 | [Get My Kernel Format](https://github.com/TheWildJames/Get_My_Kernel_Format) 49 | 50 | --- 51 | 52 | # Features 53 | 54 | - **KernelSU**: KernelSU is a root solution for Android GKI devices, it works in kernel mode and grants root permission to userspace applications directly in kernel space. 55 | - **SUSFS**: An addon root hiding kernel patches and userspace module for KernelSU. 56 | 57 | --- 58 | 59 | # Credits 60 | 61 | - **KernelSU**: Developed by [tiann](https://github.com/tiann/KernelSU). 62 | - **KernelSU-Next**: Developed by [rifsxd](https://github.com/KernelSU-Next/KernelSU-Next). 63 | - **Magic-KSU**: Developed by [5ec1cff](https://github.com/5ec1cff/KernelSU). 64 | - **SUSFS**: Developed by [simonpunk](https://gitlab.com/simonpunk/susfs4ksu.git). 65 | - **SUSFS Module**: Developed by [sidex15](https://github.com/sidex15). 66 | - **Sultan Kernels**: Developed by [kerneltoast](https://github.com/kerneltoast). 67 | 68 | Special thanks to the open-source community for their contributions! 69 | 70 | --- 71 | 72 | # Support 73 | 74 | If you encounter any issues or need help, feel free to open an issue in this repository or reach out to me. 75 | 76 | --- 77 | 78 | # Disclaimer 79 | 80 | Flashing this kernel will void your warranty, and there is always a risk of bricking your device. Please make sure to back up your data and ensure you understand the risks before proceeding. 81 | 82 | **Proceed at your own risk!** 83 | 84 | --- 85 | 86 | [Telegram](https://t.me/TheWildJames) 87 | [Telegram Group](https://t.me/WildKernels) 88 | 89 | # Special thanks to the following people for their contributions! 90 | This helps me alot! <3 91 | 92 | [simonpunk](https://gitlab.com/simonpunk/susfs4ksu.git) - Created SUSFS! 93 | [sidex15](https://github.com/sidex15) - Created module! 94 | [backslashxx](https://github.com/backslashxx) - Helped with patches! 95 | [Teemo](https://github.com/liqideqq) - Helped with patches! 96 | [幕落](https://github.com/MuLuo688) - Donation! 97 | 98 | If you have contributed and are not here please remind me! 99 | -------------------------------------------------------------------------------- /.github/workflows/build-kernel-release.yml: -------------------------------------------------------------------------------- 1 | name: Build and Release OnePlus Kernels 2 | 3 | permissions: 4 | contents: write 5 | actions: write 6 | 7 | on: 8 | workflow_dispatch: 9 | inputs: 10 | make_release: 11 | description: 'Do you want to create a release?' 12 | required: true 13 | type: boolean 14 | default: false 15 | op_model: 16 | description: 'Select the OnePlus kernels to build' 17 | required: true 18 | type: choice 19 | options: 20 | - OOS14+15+16 21 | - OOS15+16 22 | - OOS14+15 23 | - OOS16 24 | - OOS15 25 | - OOS14 26 | - android16-6.12 27 | - android15-6.6 28 | - android14-6.1 29 | - android13-5.15 30 | - android12-5.10 31 | default: OOS15 32 | ksu_options: 33 | description: 'Enter KernelSU build json' 34 | required: true 35 | type: string 36 | default: '[{"type":"ksun","hash":"next"}]' 37 | optimize_level: 38 | description: "Compiler optimization level" 39 | required: true 40 | type: choice 41 | options: [O2, O3] 42 | default: O2 43 | clean_build: 44 | description: 'Clean build (no ccache)' 45 | type: boolean 46 | default: false 47 | android12-5_10_susfs_branch_or_commit: 48 | description: 'Enter SusFS Branch or commit hash for android12-5.10' 49 | type: string 50 | default: '' 51 | android13-5_15_susfs_branch_or_commit: 52 | description: 'Enter SusFS Branch or commit hash for android13-5.15' 53 | type: string 54 | default: '' 55 | android14-6_1_susfs_branch_or_commit: 56 | description: 'Enter SusFS Branch or commit hash for android14-6.1' 57 | type: string 58 | default: '' 59 | android15-6_6_susfs_branch_or_commit: 60 | description: 'Enter SusFS Branch or commit hash for android15-6.6' 61 | type: string 62 | default: '' 63 | android16-6_12_susfs_branch_or_commit: 64 | description: 'Enter SusFS Branch or commit hash for android16-6.12' 65 | type: string 66 | default: '' 67 | 68 | jobs: 69 | set-op-model: 70 | runs-on: ubuntu-latest 71 | outputs: 72 | matrix: ${{ steps.set-matrix.outputs.matrix }} 73 | device_count: ${{ steps.set-matrix.outputs.count }} 74 | steps: 75 | - name: 📥 Checkout Code (to access configs/) 76 | uses: actions/checkout@v4 77 | with: 78 | sparse-checkout: | 79 | configs/ 80 | sparse-checkout-cone-mode: false 81 | 82 | - name: 🔍 Generate build matrix 83 | id: set-matrix 84 | shell: bash 85 | run: | 86 | set -euo pipefail 87 | echo "::group::Matrix generation" 88 | 89 | input="${{ github.event.inputs.op_model }}" 90 | ksu_options_raw='${{ github.event.inputs.ksu_options }}' 91 | if ! 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 = "next" elif .type == "KSU" then .hash = "main" else .hash end else . end else error("No type found") end)' 2>&1); then 92 | echo "::error::ksu_options validation failed: $ksu_options_normalized" 93 | exit 1 94 | fi 95 | 96 | echo "[" > matrix.json 97 | mapfile -t all_json_files < <(find configs/ -name "*.json" -print0 | xargs -0 -n1) 98 | for i in "${!all_json_files[@]}"; do 99 | file="${all_json_files[$i]}" 100 | if [ -f "$file" ]; then 101 | jq -r '.' "$file" >> matrix.json 102 | if [ $((i+1)) -lt ${#all_json_files[@]} ]; then 103 | echo "," >> matrix.json 104 | fi 105 | fi 106 | done 107 | echo "]" >> matrix.json 108 | 109 | jq_filter="." 110 | 111 | case "$input" in 112 | OOS14+15+16) 113 | ;; 114 | OOS15+16) 115 | jq_filter="map(select(.os_version == \"OOS15\" or .os_version == \"OOS16\"))" 116 | ;; 117 | OOS14+15) 118 | jq_filter="map(select(.os_version == \"OOS14\" or .os_version == \"OOS15\"))" 119 | ;; 120 | OOS16) 121 | jq_filter="map(select(.os_version == \"OOS16\"))" 122 | ;; 123 | OOS15) 124 | jq_filter="map(select(.os_version == \"OOS15\"))" 125 | ;; 126 | OOS14) 127 | jq_filter="map(select(.os_version == \"OOS14\"))" 128 | ;; 129 | android*-*.*) 130 | # Extract android version and kernel version 131 | IFS='-' read -r av kv <<< "$input" 132 | 133 | # Build android*-* only for OOS15 and OOS16 134 | jq_filter="map(select(.os_version == \"OOS15\" or .os_version == \"OOS16\")) | map(select(.android_version == \"$av\" and .kernel_version == \"$kv\"))" 135 | 136 | echo "ℹ️ Android-Kernel filter applied: $av-$kv" 137 | echo " Restricted to: OOS15 and OOS16 only" 138 | ;; 139 | *) 140 | echo "::warning::Unknown input '$input'. Using empty filter." 141 | jq_filter="map(select(false))" 142 | ;; 143 | esac 144 | 145 | filtered=$(jq -c "$jq_filter" matrix.json) 146 | count=$(jq 'length' <<<"$filtered") 147 | 148 | if [ "$count" -eq 0 ]; then 149 | echo "::error::No config files found for input '$input' after applying filters!" 150 | echo "" 151 | echo "Available configurations:" 152 | jq -r '.[] | " - \(.model) (\(.os_version), \(.android_version)-\(.kernel_version))"' matrix.json 153 | exit 1 154 | fi 155 | 156 | # For each device + each ksu option → one combined entry 157 | 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}) ]') 158 | 159 | final_count=$(echo "$merged_matrix" | jq -s length) 160 | 161 | wrapped=$(jq -n --argjson items "$merged_matrix" '{ include: $items }') 162 | 163 | echo "✅ Found $final_count device(s) to build" 164 | echo "" 165 | echo "Selected devices:" 166 | jq -r '.[] | " - \(.model) (\(.os_version), \(.android_version)-\(.kernel_version), \(.ksu_type) - \(.ksu_hash))"' <<<"$merged_matrix" 167 | 168 | echo "matrix=$(jq -c . <<< "$wrapped")" >> "$GITHUB_OUTPUT" 169 | echo "count=$count" >> "$GITHUB_OUTPUT" 170 | 171 | echo "::endgroup::" 172 | 173 | - name: Upload build matrix 174 | uses: actions/upload-artifact@v4 175 | with: 176 | name: build-matrix 177 | path: matrix.json 178 | retention-days: 1 179 | 180 | - name: 📊 Build plan summary 181 | run: | 182 | ksu_options_raw='${{ github.event.inputs.ksu_options }}' 183 | 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 = "next" elif .type == "KSU" then .hash = "main" else .hash end else . end else error("No type found") end)' 2>&1) 184 | 185 | # export KSU_OPTIONS="$ksu_options_normalized" 186 | 187 | # cat >> $GITHUB_STEP_SUMMARY << 'EOF' 188 | # ## 🎯 Build Plan 189 | 190 | # **Target:** `${{ inputs.op_model }}` 191 | # **Devices:** ${{ steps.set-matrix.outputs.count }} 192 | 193 | # **Configuration:** 194 | # - KSU Config: `"$KSU_OPTIONS"` 195 | # - Optimization: `${{ inputs.optimize_level }}` 196 | # - Clean Build/No Ccache: ${{ inputs.clean_build && '✅ Yes' || '❌ No' }} 197 | # - Create Release: ${{ inputs.make_release && '✅ Yes' || '❌ No' }} 198 | 199 | # **SUSFS Configuration:** 200 | # EOF 201 | 202 | { 203 | cat << 'EOF' 204 | ## 🎯 Build Plan 205 | 206 | **Target:** ${{ inputs.op_model }} 207 | **Devices:** ${{ steps.set-matrix.outputs.count }} 208 | 209 | **Configuration:** 210 | - KSU Config: ` 211 | EOF 212 | 213 | # Inject the shell variable 214 | printf '%s' "$ksu_options_normalized" 215 | 216 | cat << 'EOF' 217 | ` 218 | - Optimization: ${{ inputs.optimize_level }} 219 | - Clean Build/No Ccache: ${{ inputs.clean_build && '✅ Yes' || '❌ No' }} 220 | - Create Release: ${{ inputs.make_release && '✅ Yes' || '❌ No' }} 221 | 222 | **SUSFS Configuration:** 223 | EOF 224 | } >> "$GITHUB_STEP_SUMMARY" 225 | 226 | # Display SUSFS config for each kernel version 227 | declare -A susfs_inputs=( 228 | ["android12-5.10"]="${{ inputs.android12-5_10_susfs_branch_or_commit }}" 229 | ["android13-5.15"]="${{ inputs.android13-5_15_susfs_branch_or_commit }}" 230 | ["android14-6.1"]="${{ inputs.android14-6_1_susfs_branch_or_commit }}" 231 | ["android15-6.6"]="${{ inputs.android15-6_6_susfs_branch_or_commit }}" 232 | ["android16-6.12"]="${{ inputs.android16-6_12_susfs_branch_or_commit }}" 233 | ) 234 | 235 | for key in "android12-5.10" "android13-5.15" "android14-6.1" "android15-6.6" "android16-6.12"; do 236 | value="${susfs_inputs[$key]}" 237 | 238 | if [ -z "$value" ]; then 239 | echo "- $key: 🔄 auto (\`gki-$key\`)" >> $GITHUB_STEP_SUMMARY 240 | else 241 | echo "- $key: 📌 \`$value\`" >> $GITHUB_STEP_SUMMARY 242 | fi 243 | done 244 | 245 | echo "" >> $GITHUB_STEP_SUMMARY 246 | echo "> **💡 Note:** Empty values auto-map to matching \`gki-androidX-Y.Z\` branches." >> $GITHUB_STEP_SUMMARY 247 | 248 | # Add OOS restriction note for android-kernel filters 249 | if [[ "${{ inputs.op_model }}" == android*-*.* ]]; then 250 | echo "" >> $GITHUB_STEP_SUMMARY 251 | echo "> **⚠️ Android-Kernel Filter:** Only OOS15 and OOS16 devices will be built for \`${{ inputs.op_model }}\`" >> $GITHUB_STEP_SUMMARY 252 | fi 253 | 254 | build: 255 | name: build (${{ matrix.model }}, ${{ matrix.soc }}, ${{ matrix.branch }}, ${{ matrix.manifest }}, ${{ matrix.android_version }}, ${{ matrix.kernel_version }}, ${{ matrix.os_version }}, ${{ matrix.ksu_type }}) 256 | needs: set-op-model 257 | runs-on: ubuntu-latest 258 | strategy: 259 | fail-fast: false 260 | matrix: ${{ fromJSON(needs.set-op-model.outputs.matrix) }} 261 | outputs: 262 | ksun_ver: ${{ steps.build-stat.outputs.ksu_version }} 263 | ksu_ver: ${{ steps.build-stat.outputs.ksu_version }} 264 | steps: 265 | - name: 🧹 Emergency Disk Cleanup 266 | if: ${{ matrix.disk_cleanup }} 267 | run: | 268 | echo "::group::Disk Usage Before Cleanup" 269 | df -h 270 | echo "::endgroup::" 271 | 272 | echo "::group::Removing Unnecessary Software" 273 | sudo rm -rf /usr/share/dotnet 274 | sudo rm -rf /usr/local/lib/android 275 | sudo rm -rf /opt/ghc 276 | sudo rm -rf /opt/hostedtoolcache/CodeQL 277 | sudo apt-get clean 278 | if command -v docker >/dev/null 2>&1; then 279 | docker rmi $(docker images -q) 2>/dev/null || true 280 | fi 281 | echo "::endgroup::" 282 | 283 | echo "::group::Disk Usage After Cleanup" 284 | df -h 285 | AVAIL=$(df -h / | awk 'NR==2 {print $4}') 286 | echo "✅ Available space: $AVAIL" 287 | echo "::endgroup::" 288 | 289 | - name: 🔍 Resolve SUSFS branch from inputs 290 | id: susfs 291 | shell: bash 292 | if: ${{ matrix.susfs }} 293 | run: | 294 | set -euo pipefail 295 | 296 | key="${{ matrix.android_version }}-${{ matrix.kernel_version }}" 297 | 298 | echo "Looking up SUSFS branch for: $key" 299 | 300 | # Map kernel version to input value 301 | case "$key" in 302 | "android12-5.10") 303 | susfs_branch="${{ inputs.android12-5_10_susfs_branch_or_commit }}" 304 | ;; 305 | "android13-5.15") 306 | susfs_branch="${{ inputs.android13-5_15_susfs_branch_or_commit }}" 307 | ;; 308 | "android14-6.1") 309 | susfs_branch="${{ inputs.android14-6_1_susfs_branch_or_commit }}" 310 | ;; 311 | "android15-6.6") 312 | susfs_branch="${{ inputs.android15-6_6_susfs_branch_or_commit }}" 313 | ;; 314 | "android16-6.12") 315 | susfs_branch="${{ inputs.android16-6_12_susfs_branch_or_commit }}" 316 | ;; 317 | *) 318 | echo "::error::Unsupported kernel version: $key" 319 | exit 1 320 | ;; 321 | esac 322 | 323 | # If empty, it will be auto-resolved to gki-* branch in the action 324 | if [ -z "$susfs_branch" ]; then 325 | echo "ℹ️ No custom SUSFS branch specified for $key" 326 | echo " Will auto-select: gki-$key" 327 | else 328 | echo "✅ Using custom SUSFS branch for $key: '$susfs_branch'" 329 | fi 330 | 331 | echo "susfs_branch=$susfs_branch" >> "$GITHUB_OUTPUT" 332 | 333 | - name: 📥 Checkout Code 334 | uses: actions/checkout@v4 335 | with: 336 | fetch-depth: 1 337 | 338 | - name: 📦 Disk usage (pre-build) 339 | run: | 340 | echo "::group::Disk usage pre-build" 341 | df -h / 342 | du -sh "$GITHUB_WORKSPACE" 2>/dev/null || true 343 | sudo rm -rf /tmp/* || true 344 | echo "::endgroup::" 345 | 346 | - name: ♻️ Configure ccache (bounded) 347 | if: ${{ inputs.clean_build != true }} 348 | run: | 349 | if command -v ccache >/dev/null 2>&1; then 350 | echo "::group::ccache configuration" 351 | ccache -o max_size=1.0G 352 | ccache -o compression=true 353 | ccache -o compression_level=3 354 | ccache -s 355 | echo "::endgroup::" 356 | fi 357 | 358 | - name: 🧹 Prepare op_config_json (without KSU fields) 359 | id: prepare_config 360 | shell: bash 361 | run: | 362 | echo "config_json=$(jq -nc --argjson m '${{ toJSON(matrix) }}' '$m | del(.ksu_type, .ksu_hash)')" >> "$GITHUB_OUTPUT" 363 | 364 | - name: 🔨 Build Kernel 365 | id: build 366 | uses: ./.github/actions 367 | with: 368 | op_config_json: ${{ steps.prepare_config.outputs.config_json }} 369 | ksu_type: ${{ matrix.ksu_type }} 370 | ksu_branch_or_hash: ${{ matrix.ksu_hash }} 371 | susfs_commit_hash_or_branch: ${{ steps.susfs.outputs.susfs_branch }} 372 | optimize_level: ${{ inputs.optimize_level }} 373 | clean: ${{ inputs.clean_build }} 374 | 375 | - name: 📊 Build statistics 376 | id: build-stat 377 | if: always() 378 | run: | 379 | echo "::group::Build Statistics" 380 | 381 | echo "Device: ${{ matrix.model }}" 382 | echo "OS Version: ${{ matrix.os_version }}" 383 | echo "Kernel: ${{ matrix.android_version }}-${{ matrix.kernel_version }}" 384 | if [ "${{ matrix.susfs }}" = true ]; then 385 | echo "SUSFS Branch: ${{ steps.susfs.outputs.susfs_branch }}" 386 | fi 387 | echo "Status: ${{ job.status }}" 388 | 389 | if [ "${{ steps.build.outcome }}" = "success" ]; then 390 | echo "" 391 | echo "✅ Build completed successfully" 392 | echo "" 393 | echo "Outputs:" 394 | echo " - Kernel: ${{ steps.build.outputs.kernel_version }}" 395 | if [ "${{ matrix.ksu_type }}" = "KSUN" ]; then 396 | echo " - KSU Next: v${{ steps.build.outputs.ksu_version }}" 397 | echo "ksun_ver=${{ steps.build.outputs.ksu_version }}" >> "$GITHUB_OUTPUT" 398 | echo "ksu_ver=" >> "$GITHUB_OUTPUT" 399 | else 400 | echo " - KSU: v${{ steps.build.outputs.ksu_version }}" 401 | echo "ksun_ver=" >> "$GITHUB_OUTPUT" 402 | echo "ksu_ver=${{ steps.build.outputs.ksu_version }}" >> "$GITHUB_OUTPUT" 403 | fi 404 | if [ "${{ matrix.susfs }}" = true ]; then 405 | echo " - SUSFS: ${{ steps.build.outputs.susfs_version }}" 406 | fi 407 | echo " - Build time: ${{ steps.build.outputs.build_time }}s" 408 | 409 | if [ "${{ inputs.clean_build }}" != "true" ]; then 410 | echo " - ccache hit rate: ${{ steps.build.outputs.ccache_hit_rate }}" 411 | echo " - ccache direct rate: ${{ steps.build.outputs.ccache_direct_rate }}" 412 | else 413 | echo " - ccache: disabled (clean build)" 414 | fi 415 | 416 | if [ -n "${{ steps.build.outputs.warnings }}" ]; then 417 | echo " - Warnings: ${{ steps.build.outputs.warnings }}" 418 | fi 419 | else 420 | echo "❌ Build failed" 421 | fi 422 | 423 | echo "::endgroup::" 424 | 425 | - name: 📝 Job summary 426 | if: always() 427 | run: | 428 | cat >> $GITHUB_STEP_SUMMARY << EOF 429 | 430 | ### ${{ matrix.model }} (${{ matrix.os_version }}) - ${{ job.status == 'success' && '✅ Success' || '❌ Failed' }} 431 | 432 | **Kernel:** ${{ matrix.android_version }}-${{ matrix.kernel_version }} 433 | EOF 434 | 435 | if [ "${{ matrix.susfs }}" = true ]; then 436 | cat >> $GITHUB_STEP_SUMMARY << EOF 437 | **SUSFS Branch:** \`${{ steps.susfs.outputs.susfs_branch || format('(auto: gki-{0}-{1})', matrix.android_version, matrix.kernel_version) }}\` 438 | EOF 439 | fi 440 | 441 | if [ "${{ steps.build.outcome }}" = "success" ]; then 442 | cat >> $GITHUB_STEP_SUMMARY << EOF 443 | | Metric | Value | 444 | |--------|-------| 445 | | **Kernel** | ${{ steps.build.outputs.kernel_version }} | 446 | EOF 447 | if [ "${{ matrix.ksu_type }}" = "KSUN" ]; then 448 | cat >> $GITHUB_STEP_SUMMARY << EOF 449 | | **KSU Next** | v${{ steps.build.outputs.ksu_version }} | 450 | EOF 451 | else 452 | cat >> $GITHUB_STEP_SUMMARY << EOF 453 | | **KSU** | v${{ steps.build.outputs.ksu_version }} | 454 | EOF 455 | fi 456 | 457 | if [ "${{ matrix.susfs }}" = true ]; then 458 | cat >> $GITHUB_STEP_SUMMARY << EOF 459 | | **SUSFS** | ${{ steps.build.outputs.susfs_version }} | 460 | EOF 461 | fi 462 | cat >> $GITHUB_STEP_SUMMARY << EOF 463 | | **Build Time** | ${{ steps.build.outputs.build_time }}s | 464 | EOF 465 | 466 | if [ "${{ inputs.clean_build }}" != "true" ]; then 467 | cat >> $GITHUB_STEP_SUMMARY << EOF 468 | | **ccache Hit Rate** | ${{ steps.build.outputs.ccache_hit_rate }} | 469 | | **ccache Direct Rate** | ${{ steps.build.outputs.ccache_direct_rate }} | 470 | EOF 471 | fi 472 | 473 | if [ -n "${{ steps.build.outputs.warnings }}" ]; then 474 | echo "| **Warnings** | ${{ steps.build.outputs.warnings }} |" >> $GITHUB_STEP_SUMMARY 475 | fi 476 | 477 | cat >> $GITHUB_STEP_SUMMARY << EOF 478 | 479 | **SHA256:** \`${{ steps.build.outputs.image_sha256 }}\` 480 | EOF 481 | fi 482 | 483 | - name: 🧹 Final cleanup and space report 484 | if: always() 485 | run: | 486 | echo "::group::Cleanup" 487 | 488 | # Remove build artifacts but PRESERVE ccache 489 | sudo rm -rf "$GITHUB_WORKSPACE/out" || true 490 | sudo rm -rf "$GITHUB_WORKSPACE/build" || true 491 | sudo rm -rf "$GITHUB_WORKSPACE/kernel/out" || true 492 | sudo rm -rf "$GITHUB_WORKSPACE/.repo" || true 493 | sudo rm -rf /tmp/* || true 494 | 495 | # Show ccache stats (don't clear it!) 496 | if command -v ccache >/dev/null 2>&1; then 497 | echo "" 498 | echo "📊 ccache statistics after build:" 499 | ccache -s 500 | echo "" 501 | echo "💾 ccache preserved for next build" 502 | fi 503 | 504 | echo "" 505 | echo "💽 Final disk usage:" 506 | df -h / 507 | 508 | echo "::endgroup::" 509 | 510 | trigger-release: 511 | needs: [build] 512 | runs-on: ubuntu-latest 513 | if: ${{ inputs.make_release }} 514 | env: 515 | REPO_OWNER: ${{ github.repository_owner }} 516 | REPO_NAME: ${{ github.event.repository.name }} 517 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} 518 | RELEASE_NAME: '*TEST BUILD* OnePlus Kernels With KernelSU Next & SUSFS v1.5.12 *TEST BUILD*' 519 | SUSFS_BASE_VERSION: 'v1.5.12' 520 | steps: 521 | - name: 📥 Checkout code 522 | uses: actions/checkout@v4 523 | with: 524 | fetch-depth: 0 525 | 526 | - name: 🏷️ Generate and Create New Tag 527 | run: | 528 | BASE_TAG="$SUSFS_BASE_VERSION-r0" 529 | LATEST_TAG=$(gh api repos/$REPO_OWNER/$REPO_NAME/tags --jq '.[0].name') 530 | if [ -z "$LATEST_TAG" ]; then 531 | LATEST_TAG="$BASE_TAG" 532 | else 533 | LATEST_TAG=$(printf "%s\n%s\n" "$LATEST_TAG" "$BASE_TAG" | sort -rV | head -n1) 534 | fi 535 | NEW_TAG=$(echo "$LATEST_TAG" | awk -F'-r' '{suffix=$2; if (!suffix) suffix=0; suffix++; printf "%s-r%d", $1, suffix}') 536 | echo "New tag: $NEW_TAG" 537 | echo "NEW_TAG=${NEW_TAG}" >> $GITHUB_ENV 538 | git tag $NEW_TAG 539 | git push origin $NEW_TAG 540 | 541 | - name: 📥 Download Artifacts 542 | uses: actions/download-artifact@v4 543 | with: 544 | path: ./downloaded-artifacts 545 | 546 | - name: 📝 Generate Device List and Final Release Notes 547 | id: generate-notes 548 | run: | 549 | echo "=== Start building the release notes ===" 550 | 551 | # Collect build metadata 552 | declare -A device_info 553 | 554 | JSON_BUILD_DATA=$(jq -c '.' ./downloaded-artifacts/build-matrix/matrix.json) 555 | 556 | for file in $(find downloaded-artifacts -name "*.txt" -type f | sort); do 557 | if [ -f "$file" ]; then 558 | full_model=$(basename "$file" .txt) 559 | model=$(echo "$full_model" | sed -E 's/_[^_]*$//') 560 | os_version=$(sed -n '2p' "$file") 561 | kernel_version=$(sed -n '1p' "$file") 562 | device_info["$full_model"]="$model|$os_version|$kernel_version" 563 | fi 564 | done 565 | 566 | ksu_options_raw='${{ github.event.inputs.ksu_options }}' 567 | 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 = "next" elif .type == "KSU" then .hash = "main" else .hash end else . end else error("No type found") end)' 2>&1) 568 | 569 | ksun_hash=$(echo "$ksu_options_normalized" | jq -r 'map(select(.type == "KSUN")) | first | .hash // empty') 570 | ksu_hash=$(echo "$ksu_options_normalized" | jq -r 'map(select(.type == "KSU")) | first | .hash // empty') 571 | 572 | # Get workflow inputs for reference 573 | KSUN_BRANCH="$ksun_hash" 574 | KSU_BRANCH="$ksu_hash" 575 | 576 | OPTIMIZE_LEVEL="${{ inputs.optimize_level }}" 577 | CLEAN_BUILD="${{ inputs.clean_build }}" 578 | 579 | # Determine SUSFS branches used 580 | SUSFS_A12="${{ inputs.android12-5_10_susfs_branch_or_commit }}" 581 | SUSFS_A13="${{ inputs.android13-5_15_susfs_branch_or_commit }}" 582 | SUSFS_A14="${{ inputs.android14-6_1_susfs_branch_or_commit }}" 583 | SUSFS_A15="${{ inputs.android15-6_6_susfs_branch_or_commit }}" 584 | SUSFS_A16="${{ inputs.android16-6_12_susfs_branch_or_commit }}" 585 | 586 | [ -z "$SUSFS_A12" ] && SUSFS_A12="gki-android12-5.10 (auto)" 587 | [ -z "$SUSFS_A13" ] && SUSFS_A13="gki-android13-5.15 (auto)" 588 | [ -z "$SUSFS_A14" ] && SUSFS_A14="gki-android14-6.1 (auto)" 589 | [ -z "$SUSFS_A15" ] && SUSFS_A15="gki-android15-6.6 (auto)" 590 | [ -z "$SUSFS_A16" ] && SUSFS_A16="gki-android16-6.12 (auto)" 591 | 592 | cat << EOF > release_notes.md 593 | # 🎯 OnePlus Kernels with KernelSU Next & SUSFS $SUSFS_BASE_VERSION 594 | 595 | > **Build Date:** $(date -u '+%Y-%m-%d %H:%M:%S UTC') 596 | > **Build ID:** \`${{ github.run_id }}\` 597 | > **Workflow:** [\`${{ github.workflow }}\`](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}) 598 | 599 | --- 600 | 601 | ## 📦 Built Devices (${#device_info[@]} total) 602 | 603 | | Model | OS Version | Kernel Version | Features | 604 | |-------|------------|----------------|----------| 605 | EOF 606 | 607 | for full_key in $(printf '%s\n' "${!device_info[@]}" | sort); do 608 | IFS='|' read -r model os_ver kernel_ver <<< "${device_info[$full_key]}" 609 | 610 | # Use jq to extract feature flags for this model from the JSON matrix 611 | feature_flags=$(jq -r --arg MODEL "$model" ' 612 | .[] | 613 | select(.model == $MODEL) | 614 | "\(.hmbird // false)\t\(.susfs // false)\t\(.bbr // false)\t\(.bbg // false)\t\(.ttl // false)\t\(.ip_set // false)" 615 | ' <<< "$JSON_BUILD_DATA") 616 | 617 | features="" 618 | # If no match found, skip or handle error 619 | if [[ -z "$feature_flags" ]]; then 620 | echo "Warning: No JSON entry found for model: $model" >&2 621 | else 622 | IFS=$'\t' read -r hmbird susfs bbr bbg ttl ip_set <<< "$feature_flags" 623 | 624 | # Build features string based on boolean values 625 | [[ "$hmbird" == "true" ]] && features+="🐦 HMBIRD " 626 | [[ "$susfs" == "true" ]] && features+="ඞ SusFS " 627 | [[ "$bbr" == "true" ]] && features+="🚀 BBR " 628 | [[ "$bbg" == "true" ]] && features+="🛡️ BBG " 629 | [[ "$ttl" == "true" ]] && features+="⏱️ TTL " 630 | [[ "$ip_set" == "true" ]] && features+="🔧 IP_SET" 631 | fi 632 | 633 | printf "| %-13s | %-10s | %-16s | %-30s |\n" \ 634 | "$model" "$os_ver" "$kernel_ver" "$features" >> release_notes.md 635 | done 636 | 637 | cat << EOF >> release_notes.md 638 | 639 | --- 640 | 641 | ## 🔧 Build Configuration 642 | 643 | | Component | Version/Setting | 644 | |-----------|----------------| 645 | EOF 646 | if [ -n ${{ needs.build.outputs.ksun_ver }}]; then 647 | cat << EOF >> release_notes.md 648 | | **KernelSU Next Branch** | \`$KSUN_BRANCH\` | 649 | | **KernelSU Next Version** | \`${{ needs.build.outputs.ksun_ver }}\` | 650 | EOF 651 | fi 652 | if [ -n ${{ needs.build.outputs.ksu_ver }}]; then 653 | cat << EOF >> release_notes.md 654 | | **KernelSU Branch** | \`$KSU_BRANCH\` | 655 | | **KernelSU Version** | \`${{ needs.build.outputs.ksu_ver }}\` | 656 | EOF 657 | fi 658 | cat << EOF >> release_notes.md 659 | | **SUSFS Version** | \`$SUSFS_BASE_VERSION\` | 660 | | **Optimization Level** | \`$OPTIMIZE_LEVEL\` | 661 | | **Clean Build** | $( [ "$CLEAN_BUILD" = "true" ] && echo "✅ Yes (no ccache)" || echo "❌ No (ccache enabled)" ) | 662 | | **Compiler** | Clang (version varies by device) | 663 | 664 | ### 📌 SUSFS Branch Mapping 665 | 666 | | Kernel Version | SUSFS Branch/Commit | 667 | |----------------|---------------------| 668 | | android12-5.10 | \`$SUSFS_A12\` | 669 | | android13-5.15 | \`$SUSFS_A13\` | 670 | | android14-6.1 | \`$SUSFS_A14\` | 671 | | android15-6.6 | \`$SUSFS_A15\` | 672 | | android16-6.12 | \`$SUSFS_A16\` | 673 | 674 | --- 675 | 676 | ## ✨ Features & Capabilities 677 | 678 | ### 🔐 Root Management 679 | EOF 680 | if [ -n ${{ needs.build.outputs.ksun_ver }}]; then 681 | cat << EOF >> release_notes.md 682 | - **KernelSU Next** - Next-generation kernel-level root solution 683 | EOF 684 | fi 685 | if [ -n ${{ needs.build.outputs.ksu_ver }}]; then 686 | cat << EOF >> release_notes.md 687 | - **KernelSU** - Kernel-level root solution 688 | EOF 689 | fi 690 | cat << EOF >> release_notes.md 691 | - **SUSFS $SUSFS_BASE_VERSION** - Advanced hiding and security features 692 | - **Magic Mount Support** - Seamless file system modifications 693 | - **Manual Hooks** - scope_min_manual_hooks_v1.4 for better compatibility 694 | 695 | ### 🛡️ Security & Privacy 696 | - **Baseband Guard (BBG)** - LSM-based baseband security 697 | - **SUSFS Hide Features**: 698 | - ✅ SUS_PATH - Hide suspicious paths 699 | - ✅ SUS_MOUNT - Hide mount points 700 | - ✅ SUS_KSTAT - Spoof kernel statistics 701 | - ✅ TRY_UMOUNT - Auto-unmount detection 702 | - ✅ SPOOF_UNAME - Kernel version spoofing 703 | - ✅ SPOOF_CMDLINE - Boot parameters spoofing 704 | - ✅ OPEN_REDIRECT - File access redirection 705 | - ✅ SUS_MAP - Memory mapping protection 706 | - **Ptrace Leak Fix** - For kernels < 5.16 707 | 708 | ### 🚀 Performance & Networking 709 | - **BBR** - Improved TCP congestion control 710 | - **Wireguard** - Built-in VPN support 711 | - **IP Set Support** - Advanced firewall capabilities 712 | - **TTL Target Support** - Network packet manipulation 713 | - **LTO (Link Time Optimization)** - Optimized binary size and performance 714 | - **ccache-accelerated builds** - Faster compilation times 715 | 716 | ### 🔧 System Features 717 | - **TMPFS_XATTR** - Extended attributes for tmpfs (Mountify support) 718 | - **TMPFS_POSIX_ACL** - POSIX ACLs for tmpfs 719 | - **HMBIRD SCX** - Scheduler extensions for all sm8750 devices 720 | 721 | --- 722 | 723 | ## 📱 Manager Applications 724 | 725 | ### Official Manager 726 | EOF 727 | if [ -n ${{ needs.build.outputs.ksun_ver }}]; then 728 | cat << EOF >> release_notes.md 729 | - **KernelSU Next Manager** 730 | → [GitHub Release](https://github.com/KernelSU-Next/KernelSU-Next/releases) 731 | EOF 732 | fi 733 | if [ -n ${{ needs.build.outputs.ksu_ver }}]; then 734 | cat << EOF >> release_notes.md 735 | - **KernelSU Next Manager** 736 | → [GitHub Release](https://github.com/KernelSU-Next/KernelSU-Next/releases) 737 | EOF 738 | fi 739 | cat << EOF >> release_notes.md 740 | ### Community Managers 741 | - **WildKSU Manager** (Recommended for additional features) 742 | → [GitHub Release](https://github.com/WildKernels/Wild_KSU/releases) 743 | 744 | ### Required Module 745 | - **KSU SUSFS Module** (Required for SUSFS features) 746 | → [GitHub Release](https://github.com/sidex15/ksu_module_susfs/releases) 747 | 748 | ### Recomended Flasher 749 | - **Kernel Flasher** (Required for flashing AnyKernel3 zips and backups and OTA) 750 | → [GitHub Release](https://github.com/fatalcoder524/KernelFlasher/releases) 751 | 752 | --- 753 | 754 | ## 📥 Installation Instructions 755 | 756 | ### Prerequisites 757 | - Unlocked bootloader 758 | - Backup your current boot image 759 | - Have root access using Magisk / KernelSU (Any forks) / Apatch 760 | 761 | ### Via Kernel Flasher 762 | 1. Download the appropriate ZIP for your device 763 | 2. Flash the ZIP file using Kernel Flasher 764 | 3. Reboot system 765 | 4. Install KernelSU-Next/WildSU Manager 766 | 5. Install SUSFS module from manager 767 | 768 | --- 769 | 770 | ## 📜 Changelog 771 | 772 | ### This Release 773 | - Updated SUSFS to v1.5.12 774 | - Added HMBIRD support for all sm8750 devices. 775 | - Improved ccache build system 776 | - Enhanced SUSFS hiding capabilities 777 | - Added IP_SET and TTL support 778 | - Added TMPFS_XATTR and TMPFS_POSIX_ACL support for Mountify 779 | - Added Ptrace leak fix for kernels < 5.16 780 | - Compiler optimizations (${{ inputs.optimize_level }}) 781 | 782 | ### Previous Releases 783 | See [Releases Page](${{ github.server_url }}/${{ github.repository }}/releases) 784 | 785 | --- 786 | 787 | ## 🙏 Credits 788 | 789 | - **KernelSU Next Team** - Root solution 790 | - **KernelSU Team** - Root solution 791 | - **simonpunk** - SUSFS development 792 | - **OnePlus** - Kernel source code 793 | - **Community Contributors** - Testing and feedback 794 | 795 | --- 796 | 797 | **⚡ Built with ❤️ by the community** 798 | 799 | > *This is an unofficial build. Use at your own risk.* 800 | EOF 801 | 802 | echo "--- Final Release Notes ---" 803 | cat release_notes.md 804 | 805 | - name: 🚀 Create GitHub Release 806 | run: | 807 | gh release create "${{ env.NEW_TAG }}" \ 808 | --repo "${{ env.REPO_OWNER }}/${{ env.REPO_NAME }}" \ 809 | --title "${{ env.RELEASE_NAME }}" \ 810 | --notes-file release_notes.md \ 811 | --prerelease 812 | 813 | - name: 📤 Upload Release Assets Dynamically 814 | run: | 815 | for file in ./downloaded-artifacts/*/*.zip; do 816 | if [ -f "$file" ]; then 817 | echo "Uploading $file..." 818 | gh release upload "${{ env.NEW_TAG }}" "$file" --clobber 819 | fi 820 | done 821 | 822 | - name: 📊 Release summary 823 | if: success() 824 | run: | 825 | cat >> $GITHUB_STEP_SUMMARY << EOF 826 | 827 | --- 828 | 829 | ## 🎉 Release Created Successfully 830 | 831 | **Tag:** [\`${{ env.NEW_TAG }}\`](${{ github.server_url }}/${{ github.repository }}/releases/tag/${{ env.NEW_TAG }}) 832 | **Kernels:** $(find ./downloaded-artifacts -name "*.zip" | wc -l) 833 | 834 | ### 📦 Assets 835 | EOF 836 | 837 | for zip in ./downloaded-artifacts/*/*.zip; do 838 | if [ -f "$zip" ]; then 839 | name=$(basename "$zip") 840 | size=$(stat -c%s "$zip") 841 | size_mb=$(echo "scale=2; $size / 1024 / 1024" | bc) 842 | echo "- \`$name\` (${size_mb} MB)" >> $GITHUB_STEP_SUMMARY 843 | fi 844 | done 845 | -------------------------------------------------------------------------------- /.github/workflows/clean-up.yml: -------------------------------------------------------------------------------- 1 | name: Cleanup CCache 🧹 2 | 3 | on: 4 | workflow_dispatch: 5 | inputs: 6 | cleanup_type: 7 | type: choice 8 | description: 'Cleanup target' 9 | required: true 10 | default: 'cache_only' 11 | options: 12 | - cache_only # Only clean caches 13 | - runs_only # Only clean workflow runs 14 | - full_cleanup # Both caches and runs 15 | - analyze_only # Just analyze, don't delete 16 | 17 | device_filter: 18 | type: choice 19 | description: 'Device cache to clean' 20 | required: false 21 | default: 'ALL' 22 | options: 23 | - ALL 24 | # Kernel Versions 25 | - android15-6.6 26 | - android14-6.1 27 | - android14-5.15 28 | - android13-5.15 29 | - android13-5.10 30 | - android12-5.10 31 | # OnePlus Phones 32 | - OP13 33 | - OP13-CPH 34 | - OP13-PJZ 35 | - OP13r 36 | - OP13S 37 | - OP13T 38 | - OP12 39 | - OP12r 40 | - OP11 41 | - OP11r 42 | - OP10pro 43 | - OP10t 44 | # OnePlus Nord Series 45 | - OP-Nord-5 46 | - OP-NORD-4 47 | - OP-NORD-4-CE 48 | - OP-NORD-CE4-LITE 49 | # OnePlus Ace Series 50 | - OP-ACE-6 51 | - OP-ACE-5-PRO 52 | - OP-ACE-5 53 | - OP-ACE-3-PRO 54 | - OP-ACE-3V 55 | - OP-ACE-3 56 | - OP-ACE-2-PRO 57 | - OP-ACE-2 58 | # OnePlus Tablets & Others 59 | - OP-OPEN 60 | - OP-PAD-3 61 | - OP-PAD-2-PRO 62 | - OP-PAD-2 63 | - OP-PAD-PRO 64 | 65 | cache_pattern: 66 | type: choice 67 | description: 'Cache type to clean' 68 | required: false 69 | default: 'all_caches' 70 | options: 71 | - all_caches # All cache types 72 | - ccache_only # Only ccache (kernel builds) 73 | - ccache_stale # Only stale ccache (>14 days) 74 | - apt_only # Only apt packages 75 | - kernel_only # Only kernel-related caches 76 | - old_only # Only caches older than 7 days 77 | 78 | cache_age_days: 79 | description: 'Delete caches older than N days' 80 | required: false 81 | default: '7' 82 | 83 | keep_recent_runs: 84 | description: 'Keep N most recent successful runs' 85 | required: false 86 | default: '3' 87 | 88 | days_to_keep: 89 | description: 'Keep runs from last N days' 90 | required: false 91 | default: '7' 92 | 93 | dry_run: 94 | description: 'Dry run (show what would be deleted)' 95 | required: false 96 | type: boolean 97 | default: false 98 | 99 | force_cleanup: 100 | description: 'Force cleanup even if usage is low' 101 | required: false 102 | type: boolean 103 | default: false 104 | 105 | permissions: 106 | actions: write 107 | contents: read 108 | 109 | jobs: 110 | analyze: 111 | runs-on: ubuntu-latest 112 | outputs: 113 | should_cleanup: ${{ steps.analysis.outputs.should_cleanup }} 114 | total_cache_size: ${{ steps.analysis.outputs.total_size }} 115 | cache_count: ${{ steps.analysis.outputs.cache_count }} 116 | usage_percent: ${{ steps.analysis.outputs.usage_percent }} 117 | ccache_count: ${{ steps.analysis.outputs.ccache_count }} 118 | ccache_size: ${{ steps.analysis.outputs.ccache_size }} 119 | steps: 120 | - name: 📊 Analyze Repository Health 121 | id: analysis 122 | uses: actions/github-script@v7 123 | with: 124 | script: | 125 | const { owner, repo } = context.repo; 126 | const forceCleanup = '${{ inputs.force_cleanup }}' === 'true'; 127 | 128 | console.log('🔍 Analyzing repository cache health...\n'); 129 | 130 | let page = 1; 131 | let totalCacheSize = 0; 132 | let cacheCount = 0; 133 | let oldestCache = null; 134 | let newestCache = null; 135 | 136 | const cachesByType = { 137 | ccache: { size: 0, count: 0 }, 138 | apt: { size: 0, count: 0 }, 139 | kernel: { size: 0, count: 0 }, 140 | other: { size: 0, count: 0 } 141 | }; 142 | 143 | const cachesByDevice = new Map(); 144 | const cacheAgeDistribution = { 145 | fresh: 0, // < 7 days 146 | recent: 0, // 7-14 days 147 | old: 0, // 14-30 days 148 | stale: 0 // > 30 days 149 | }; 150 | 151 | // Collect all cache data 152 | while (true) { 153 | const res = await github.rest.actions.getActionsCacheList({ 154 | owner, 155 | repo, 156 | per_page: 100, 157 | page: page 158 | }); 159 | 160 | const caches = res.data.actions_caches; 161 | if (!caches || caches.length === 0) break; 162 | 163 | for (const cache of caches) { 164 | totalCacheSize += cache.size_in_bytes; 165 | cacheCount++; 166 | 167 | const cacheDate = new Date(cache.created_at); 168 | const ageDays = Math.floor((new Date() - cacheDate) / (1000 * 60 * 60 * 24)); 169 | 170 | // Age distribution 171 | if (ageDays < 7) cacheAgeDistribution.fresh++; 172 | else if (ageDays < 14) cacheAgeDistribution.recent++; 173 | else if (ageDays < 30) cacheAgeDistribution.old++; 174 | else cacheAgeDistribution.stale++; 175 | 176 | if (!oldestCache || cacheDate < new Date(oldestCache.created_at)) { 177 | oldestCache = cache; 178 | } 179 | if (!newestCache || cacheDate > new Date(newestCache.created_at)) { 180 | newestCache = cache; 181 | } 182 | 183 | // Categorize by type 184 | if (cache.key.startsWith('ccache-')) { 185 | cachesByType.ccache.size += cache.size_in_bytes; 186 | cachesByType.ccache.count++; 187 | 188 | // Extract device name from ccache key 189 | const match = cache.key.match(/ccache-([^-]+)-/); 190 | if (match) { 191 | const device = match[1]; 192 | if (!cachesByDevice.has(device)) { 193 | cachesByDevice.set(device, { 194 | size: 0, 195 | count: 0, 196 | lastAccessed: cache.last_accessed_at, 197 | oldestCache: ageDays, 198 | newestCache: ageDays 199 | }); 200 | } 201 | const deviceData = cachesByDevice.get(device); 202 | deviceData.size += cache.size_in_bytes; 203 | deviceData.count++; 204 | deviceData.oldestCache = Math.max(deviceData.oldestCache, ageDays); 205 | deviceData.newestCache = Math.min(deviceData.newestCache, ageDays); 206 | if (new Date(cache.last_accessed_at) > new Date(deviceData.lastAccessed)) { 207 | deviceData.lastAccessed = cache.last_accessed_at; 208 | } 209 | } 210 | } else if (cache.key.includes('apt')) { 211 | cachesByType.apt.size += cache.size_in_bytes; 212 | cachesByType.apt.count++; 213 | } else if (cache.key.includes('kernel') || cache.key.includes('android')) { 214 | cachesByType.kernel.size += cache.size_in_bytes; 215 | cachesByType.kernel.count++; 216 | } else { 217 | cachesByType.other.size += cache.size_in_bytes; 218 | cachesByType.other.count++; 219 | } 220 | } 221 | 222 | if (caches.length < 100) break; 223 | page++; 224 | } 225 | 226 | // Calculate metrics 227 | const totalGB = (totalCacheSize / 1024 / 1024 / 1024).toFixed(2); 228 | const limit = 10; // 10 GB GitHub limit 229 | const usagePercent = ((totalCacheSize / (limit * 1024 * 1024 * 1024)) * 100).toFixed(1); 230 | 231 | // Determine if cleanup is needed 232 | const shouldCleanup = forceCleanup || parseFloat(usagePercent) > 75; 233 | 234 | // Health status 235 | let healthEmoji = '🟢'; 236 | let healthStatus = 'Healthy'; 237 | if (usagePercent > 90) { 238 | healthEmoji = '🔴'; 239 | healthStatus = 'Critical'; 240 | } else if (usagePercent > 75) { 241 | healthEmoji = '🟡'; 242 | healthStatus = 'Warning'; 243 | } 244 | 245 | // Output for next jobs 246 | core.setOutput('should_cleanup', shouldCleanup.toString()); 247 | core.setOutput('total_size', totalCacheSize.toString()); 248 | core.setOutput('cache_count', cacheCount.toString()); 249 | core.setOutput('usage_percent', usagePercent); 250 | core.setOutput('ccache_count', cachesByType.ccache.count.toString()); 251 | core.setOutput('ccache_size', cachesByType.ccache.size.toString()); 252 | 253 | // Generate detailed summary 254 | let summary = core.summary 255 | .addHeading(`${healthEmoji} Cache Health Analysis - ${healthStatus}`) 256 | .addRaw(`\n### 📊 Overall Statistics\n\n`) 257 | .addTable([ 258 | [{data: 'Metric', header: true}, {data: 'Value', header: true}], 259 | ['Total Caches', cacheCount.toString()], 260 | ['Total Size', `${totalGB} GB`], 261 | ['Limit', `${limit} GB`], 262 | ['Usage', `${usagePercent}%`], 263 | ['Available', `${(limit - parseFloat(totalGB)).toFixed(2)} GB`], 264 | ['Status', healthStatus] 265 | ]); 266 | 267 | // Cache breakdown by type 268 | summary.addRaw(`\n### 🗂️ Cache Breakdown by Type\n\n`) 269 | .addTable([ 270 | [{data: 'Type', header: true}, {data: 'Count', header: true}, {data: 'Size (GB)', header: true}, {data: 'Percentage', header: true}], 271 | ['ccache (Kernel Builds)', 272 | cachesByType.ccache.count.toString(), 273 | (cachesByType.ccache.size / 1024 / 1024 / 1024).toFixed(2), 274 | `${((cachesByType.ccache.size / totalCacheSize) * 100).toFixed(1)}%` 275 | ], 276 | ['Kernel-related', 277 | cachesByType.kernel.count.toString(), 278 | (cachesByType.kernel.size / 1024 / 1024 / 1024).toFixed(2), 279 | `${((cachesByType.kernel.size / totalCacheSize) * 100).toFixed(1)}%` 280 | ], 281 | ['APT Packages', 282 | cachesByType.apt.count.toString(), 283 | (cachesByType.apt.size / 1024 / 1024 / 1024).toFixed(2), 284 | `${((cachesByType.apt.size / totalCacheSize) * 100).toFixed(1)}%` 285 | ], 286 | ['Other', 287 | cachesByType.other.count.toString(), 288 | (cachesByType.other.size / 1024 / 1024 / 1024).toFixed(2), 289 | `${((cachesByType.other.size / totalCacheSize) * 100).toFixed(1)}%` 290 | ] 291 | ]); 292 | 293 | // ccache-specific statistics 294 | if (cachesByType.ccache.count > 0) { 295 | const avgCcacheSize = cachesByType.ccache.size / cachesByType.ccache.count; 296 | const avgCcacheSizeMB = (avgCcacheSize / 1024 / 1024).toFixed(2); 297 | const ccachePercent = ((cachesByType.ccache.size / totalCacheSize) * 100).toFixed(1); 298 | 299 | summary.addRaw(`\n### ⚡ ccache Statistics\n\n`) 300 | .addTable([ 301 | [{data: 'Metric', header: true}, {data: 'Value', header: true}], 302 | ['Total ccache Entries', cachesByType.ccache.count.toString()], 303 | ['Total ccache Size', `${(cachesByType.ccache.size / 1024 / 1024 / 1024).toFixed(2)} GB`], 304 | ['Average Cache Size', `${avgCcacheSizeMB} MB`], 305 | ['Percentage of Total', `${ccachePercent}%`], 306 | ['Unique Devices', cachesByDevice.size.toString()] 307 | ]); 308 | 309 | // ccache recommendations 310 | if (parseFloat(ccachePercent) > 80) { 311 | summary.addRaw(`\n⚠️ **ccache dominates storage** (${ccachePercent}%)\n`) 312 | .addRaw(`- Consider reducing \`CCACHE_MAXSIZE\` in build workflow\n`) 313 | .addRaw(`- Clean stale device caches not actively built\n`) 314 | .addRaw(`- Use \`clean_build\` option occasionally to verify builds\n`); 315 | } 316 | } 317 | 318 | // Age distribution 319 | summary.addRaw(`\n### 📅 Cache Age Distribution\n\n`) 320 | .addTable([ 321 | [{data: 'Age Range', header: true}, {data: 'Count', header: true}, {data: 'Percentage', header: true}], 322 | ['Fresh (< 7 days)', cacheAgeDistribution.fresh.toString(), `${((cacheAgeDistribution.fresh / cacheCount) * 100).toFixed(1)}%`], 323 | ['Recent (7-14 days)', cacheAgeDistribution.recent.toString(), `${((cacheAgeDistribution.recent / cacheCount) * 100).toFixed(1)}%`], 324 | ['Old (14-30 days)', cacheAgeDistribution.old.toString(), `${((cacheAgeDistribution.old / cacheCount) * 100).toFixed(1)}%`], 325 | ['Stale (> 30 days)', cacheAgeDistribution.stale.toString(), `${((cacheAgeDistribution.stale / cacheCount) * 100).toFixed(1)}%`] 326 | ]); 327 | 328 | // Top devices by cache size 329 | if (cachesByDevice.size > 0) { 330 | const topDevices = Array.from(cachesByDevice.entries()) 331 | .sort((a, b) => b[1].size - a[1].size) 332 | .slice(0, 15); 333 | 334 | summary.addRaw(`\n### 📱 Top 15 Devices by Cache Size\n\n`) 335 | .addTable([ 336 | [{data: 'Device', header: true}, {data: 'Caches', header: true}, {data: 'Size (GB)', header: true}, {data: 'Age Range (days)', header: true}], 337 | ...topDevices.map(([device, data]) => [ 338 | device, 339 | data.count.toString(), 340 | (data.size / 1024 / 1024 / 1024).toFixed(2), 341 | `${data.newestCache}-${data.oldestCache}` 342 | ]) 343 | ]); 344 | 345 | // Identify inactive devices 346 | const now = new Date(); 347 | const inactiveThreshold = 30; // days 348 | const inactiveDevices = Array.from(cachesByDevice.entries()) 349 | .filter(([_, data]) => { 350 | const daysSinceAccess = Math.floor((now - new Date(data.lastAccessed)) / (1000 * 60 * 60 * 24)); 351 | return daysSinceAccess > inactiveThreshold; 352 | }) 353 | .sort((a, b) => b[1].size - a[1].size); 354 | 355 | if (inactiveDevices.length > 0) { 356 | summary.addRaw(`\n### 🚫 Inactive Devices (Not accessed in ${inactiveThreshold}+ days)\n\n`) 357 | .addTable([ 358 | [{data: 'Device', header: true}, {data: 'Size (GB)', header: true}, {data: 'Days Since Access', header: true}], 359 | ...inactiveDevices.slice(0, 10).map(([device, data]) => [ 360 | device, 361 | (data.size / 1024 / 1024 / 1024).toFixed(2), 362 | Math.floor((now - new Date(data.lastAccessed)) / (1000 * 60 * 60 * 24)).toString() 363 | ]) 364 | ]); 365 | 366 | const inactiveSizeGB = inactiveDevices.reduce((sum, [_, data]) => sum + data.size, 0) / 1024 / 1024 / 1024; 367 | summary.addRaw(`\n💡 **Potential savings:** ${inactiveSizeGB.toFixed(2)} GB by cleaning inactive devices\n`); 368 | } 369 | } 370 | 371 | // Age information 372 | if (oldestCache && newestCache) { 373 | const oldestDate = new Date(oldestCache.created_at); 374 | const newestDate = new Date(newestCache.created_at); 375 | const daysDiff = Math.floor((newestDate - oldestDate) / (1000 * 60 * 60 * 24)); 376 | 377 | summary.addRaw(`\n### 📅 Cache Age Information\n\n`) 378 | .addTable([ 379 | [{data: 'Metric', header: true}, {data: 'Value', header: true}], 380 | ['Oldest Cache', oldestDate.toISOString().split('T')[0]], 381 | ['Newest Cache', newestDate.toISOString().split('T')[0]], 382 | ['Age Range', `${daysDiff} days`] 383 | ]); 384 | } 385 | 386 | // Recommendations 387 | summary.addRaw(`\n### 💡 Recommendations\n\n`); 388 | 389 | if (parseFloat(usagePercent) > 90) { 390 | summary.addRaw(`- 🔴 **URGENT:** Cache usage is critical (${usagePercent}%)\n`) 391 | .addRaw(`- Run cleanup immediately with \`device_filter: ALL\`\n`) 392 | .addRaw(`- Consider cleaning old device caches\n`) 393 | .addRaw(`- Review ccache size limits in build workflows\n`); 394 | } else if (parseFloat(usagePercent) > 75) { 395 | summary.addRaw(`- 🟡 **WARNING:** Cache usage is high (${usagePercent}%)\n`) 396 | .addRaw(`- Schedule cleanup soon\n`) 397 | .addRaw(`- Consider targeting specific devices\n`); 398 | } else { 399 | summary.addRaw(`- 🟢 Cache usage is healthy (${usagePercent}%)\n`) 400 | .addRaw(`- Regular weekly cleanup recommended\n`) 401 | .addRaw(`- No immediate action required\n`); 402 | } 403 | 404 | // Stale cache recommendations 405 | if (cacheAgeDistribution.stale > 0) { 406 | const staleSizeEstimate = (cacheAgeDistribution.stale / cacheCount) * totalCacheSize; 407 | const staleSizeGB = (staleSizeEstimate / 1024 / 1024 / 1024).toFixed(2); 408 | summary.addRaw(`\n- 📦 **${cacheAgeDistribution.stale} stale caches** (>30 days old)\n`) 409 | .addRaw(`- Estimated size: ~${staleSizeGB} GB\n`) 410 | .addRaw(`- Run with \`cache_pattern: ccache_stale\` to clean\n`); 411 | } 412 | 413 | if (shouldCleanup && !forceCleanup) { 414 | summary.addRaw(`\n⚠️ **Automatic cleanup will proceed** (usage > 75%)\n`); 415 | } else if (forceCleanup) { 416 | summary.addRaw(`\n⚡ **Force cleanup enabled** - proceeding regardless of usage\n`); 417 | } 418 | 419 | summary.write(); 420 | 421 | console.log(`\n✅ Analysis complete:`); 422 | console.log(` - Total: ${totalGB} GB (${usagePercent}%)`); 423 | console.log(` - Caches: ${cacheCount}`); 424 | console.log(` - ccache: ${cachesByType.ccache.count} (${(cachesByType.ccache.size / 1024 / 1024 / 1024).toFixed(2)} GB)`); 425 | console.log(` - Devices: ${cachesByDevice.size}`); 426 | console.log(` - Cleanup needed: ${shouldCleanup}`); 427 | 428 | cleanup-caches: 429 | runs-on: ubuntu-latest 430 | needs: analyze 431 | if: | 432 | always() && 433 | (inputs.cleanup_type == 'cache_only' || inputs.cleanup_type == 'full_cleanup') && 434 | (inputs.cleanup_type != 'analyze_only') 435 | 436 | steps: 437 | - name: 🗑️ Smart Cache Cleanup 438 | uses: actions/github-script@v7 439 | with: 440 | script: | 441 | const { owner, repo } = context.repo; 442 | const deviceFilter = '${{ inputs.device_filter }}'; 443 | const cachePattern = '${{ inputs.cache_pattern }}'; 444 | const dryRun = '${{ inputs.dry_run }}' === 'true'; 445 | const cacheAgeDays = parseInt('${{ inputs.cache_age_days }}'); 446 | const shouldCleanup = '${{ needs.analyze.outputs.should_cleanup }}' === 'true'; 447 | const forceCleanup = '${{ inputs.force_cleanup }}' === 'true'; 448 | 449 | console.log(`🎯 Configuration:`); 450 | console.log(` - Device Filter: ${deviceFilter}`); 451 | console.log(` - Cache Pattern: ${cachePattern}`); 452 | console.log(` - Age Threshold: ${cacheAgeDays} days`); 453 | console.log(` - Dry Run: ${dryRun}`); 454 | console.log(` - Should Cleanup: ${shouldCleanup}`); 455 | console.log(` - Force Cleanup: ${forceCleanup}\n`); 456 | 457 | // Check if we should proceed 458 | if (!shouldCleanup && !forceCleanup && !dryRun) { 459 | console.log('ℹ️ Cache usage is healthy, skipping cleanup'); 460 | console.log('💡 Use force_cleanup=true to cleanup anyway'); 461 | core.summary 462 | .addHeading('ℹ️ Cleanup Skipped') 463 | .addRaw(`Cache usage is healthy (${${{ needs.analyze.outputs.usage_percent }}}%)\n\n`) 464 | .addRaw('No cleanup needed at this time.\n') 465 | .write(); 466 | return; 467 | } 468 | 469 | const cutoffDate = new Date(); 470 | cutoffDate.setDate(cutoffDate.getDate() - cacheAgeDays); 471 | 472 | // For stale ccache pattern, use 14 days 473 | const staleCutoffDate = new Date(); 474 | staleCutoffDate.setDate(staleCutoffDate.getDate() - 14); 475 | 476 | let totalDeleted = 0; 477 | let totalSize = 0; 478 | let page = 1; 479 | const deletedCaches = []; 480 | const skippedCaches = []; 481 | 482 | // Track statistics by category 483 | const deletionStats = { 484 | ccache: { count: 0, size: 0 }, 485 | apt: { count: 0, size: 0 }, 486 | kernel: { count: 0, size: 0 }, 487 | other: { count: 0, size: 0 } 488 | }; 489 | 490 | // Helper function to check if cache should be deleted 491 | function shouldDeleteCache(cache) { 492 | const cacheKey = cache.key; 493 | const cacheDate = new Date(cache.created_at); 494 | const ageDays = Math.floor((new Date() - cacheDate) / (1000 * 60 * 60 * 24)); 495 | 496 | // Device filter logic 497 | const deviceMatch = 498 | deviceFilter === 'ALL' || 499 | cacheKey.includes(deviceFilter) || 500 | cacheKey.includes(`-${deviceFilter}-`) || 501 | cacheKey.startsWith(`${deviceFilter}-`); 502 | 503 | if (!deviceMatch) { 504 | return { delete: false, reason: 'device_filter' }; 505 | } 506 | 507 | // Age filter for 'old_only' pattern 508 | if (cachePattern === 'old_only' && cacheDate >= cutoffDate) { 509 | return { delete: false, reason: 'too_new' }; 510 | } 511 | 512 | // Cache pattern logic 513 | let patternMatch = false; 514 | let category = 'other'; 515 | 516 | switch (cachePattern) { 517 | case 'ccache_only': 518 | patternMatch = cacheKey.startsWith('ccache-'); 519 | category = 'ccache'; 520 | break; 521 | 522 | case 'ccache_stale': 523 | patternMatch = cacheKey.startsWith('ccache-') && cacheDate < staleCutoffDate; 524 | category = 'ccache'; 525 | break; 526 | 527 | case 'apt_only': 528 | patternMatch = cacheKey.includes('apt-cache') || cacheKey.includes('apt-'); 529 | category = 'apt'; 530 | break; 531 | 532 | case 'kernel_only': 533 | patternMatch = cacheKey.includes('kernel-') || 534 | cacheKey.includes('android') || 535 | cacheKey.startsWith('ccache-'); 536 | if (cacheKey.startsWith('ccache-')) category = 'ccache'; 537 | else category = 'kernel'; 538 | break; 539 | 540 | case 'old_only': 541 | patternMatch = cacheDate < cutoffDate; 542 | if (cacheKey.startsWith('ccache-')) category = 'ccache'; 543 | else if (cacheKey.includes('apt')) category = 'apt'; 544 | else if (cacheKey.includes('kernel')) category = 'kernel'; 545 | break; 546 | 547 | case 'all_caches': 548 | default: 549 | patternMatch = true; 550 | if (cacheKey.startsWith('ccache-')) category = 'ccache'; 551 | else if (cacheKey.includes('apt')) category = 'apt'; 552 | else if (cacheKey.includes('kernel')) category = 'kernel'; 553 | } 554 | 555 | return { 556 | delete: patternMatch, 557 | reason: patternMatch ? 'match' : 'pattern_mismatch', 558 | category: category 559 | }; 560 | } 561 | 562 | // Fetch and process caches 563 | console.log('🔍 Scanning caches...\n'); 564 | 565 | while (true) { 566 | const res = await github.rest.actions.getActionsCacheList({ 567 | owner, 568 | repo, 569 | per_page: 100, 570 | page: page 571 | }); 572 | 573 | const caches = res.data.actions_caches; 574 | if (!caches || caches.length === 0) break; 575 | 576 | for (const cache of caches) { 577 | const decision = shouldDeleteCache(cache); 578 | const sizeMB = (cache.size_in_bytes / 1024 / 1024).toFixed(2); 579 | const agedays = Math.floor((new Date() - new Date(cache.created_at)) / (1000 * 60 * 60 * 24)); 580 | 581 | if (decision.delete) { 582 | deletedCaches.push({ 583 | key: cache.key, 584 | size: sizeMB, 585 | sizeBytes: cache.size_in_bytes, 586 | age: agedays, 587 | created: cache.created_at, 588 | id: cache.id, 589 | category: decision.category 590 | }); 591 | 592 | if (dryRun) { 593 | console.log(`🔍 Would delete: ${cache.key}`); 594 | console.log(` Size: ${sizeMB} MB | Age: ${agedays} days | Type: ${decision.category}`); 595 | } else { 596 | console.log(`🗑️ Deleting: ${cache.key}`); 597 | console.log(` Size: ${sizeMB} MB | Age: ${agedays} days | Type: ${decision.category}`); 598 | 599 | try { 600 | await github.rest.actions.deleteActionsCacheById({ 601 | owner, 602 | repo, 603 | cache_id: cache.id 604 | }); 605 | totalDeleted++; 606 | totalSize += cache.size_in_bytes; 607 | 608 | // Update category stats 609 | deletionStats[decision.category].count++; 610 | deletionStats[decision.category].size += cache.size_in_bytes; 611 | } catch (error) { 612 | console.log(` ⚠️ Failed: ${error.message}`); 613 | skippedCaches.push({ 614 | key: cache.key, 615 | reason: error.message 616 | }); 617 | } 618 | } 619 | } else if (decision.reason !== 'device_filter') { 620 | // Only log non-device-filter skips in verbose mode 621 | // console.log(`⏭️ Skipping: ${cache.key} (${decision.reason})`); 622 | } 623 | } 624 | 625 | if (caches.length < 100) break; 626 | page++; 627 | } 628 | 629 | const sizeMB = (totalSize / 1024 / 1024).toFixed(2); 630 | const sizeGB = (totalSize / 1024 / 1024 / 1024).toFixed(2); 631 | 632 | console.log(`\n✅ ${dryRun ? 'Would delete' : 'Deleted'} ${totalDeleted} caches`); 633 | console.log(`📊 Space ${dryRun ? 'would be' : ''} freed: ${sizeMB} MB (${sizeGB} GB)`); 634 | 635 | // Generate detailed summary 636 | let summary = core.summary 637 | .addHeading(`🧹 Cache Cleanup ${dryRun ? 'Preview' : 'Summary'}`) 638 | .addTable([ 639 | [{data: 'Metric', header: true}, {data: 'Value', header: true}], 640 | ['Caches ' + (dryRun ? 'to Delete' : 'Deleted'), totalDeleted.toString()], 641 | ['Space ' + (dryRun ? 'to Free' : 'Freed'), `${sizeMB} MB (${sizeGB} GB)`], 642 | ['Device Filter', deviceFilter], 643 | ['Cache Pattern', cachePattern], 644 | ['Age Threshold', `${cacheAgeDays} days`] 645 | ]); 646 | 647 | // Deletion breakdown by type 648 | if (totalDeleted > 0 || dryRun) { 649 | summary.addHeading('📊 Deletion Breakdown by Type', 3) 650 | .addTable([ 651 | [{data: 'Type', header: true}, {data: 'Count', header: true}, {data: 'Size (GB)', header: true}, {data: 'Percentage', header: true}], 652 | ['ccache', 653 | deletionStats.ccache.count.toString(), 654 | (deletionStats.ccache.size / 1024 / 1024 / 1024).toFixed(2), 655 | totalSize > 0 ? `${((deletionStats.ccache.size / totalSize) * 100).toFixed(1)}%` : '0%' 656 | ], 657 | ['Kernel-related', 658 | deletionStats.kernel.count.toString(), 659 | (deletionStats.kernel.size / 1024 / 1024 / 1024).toFixed(2), 660 | totalSize > 0 ? `${((deletionStats.kernel.size / totalSize) * 100).toFixed(1)}%` : '0%' 661 | ], 662 | ['APT Packages', 663 | deletionStats.apt.count.toString(), 664 | (deletionStats.apt.size / 1024 / 1024 / 1024).toFixed(2), 665 | totalSize > 0 ? `${((deletionStats.apt.size / totalSize) * 100).toFixed(1)}%` : '0%' 666 | ], 667 | ['Other', 668 | deletionStats.other.count.toString(), 669 | (deletionStats.other.size / 1024 / 1024 / 1024).toFixed(2), 670 | totalSize > 0 ? `${((deletionStats.other.size / totalSize) * 100).toFixed(1)}%` : '0%' 671 | ] 672 | ]); 673 | } 674 | 675 | // Add top 20 largest caches 676 | if (deletedCaches.length > 0) { 677 | const topCaches = deletedCaches 678 | .sort((a, b) => parseFloat(b.size) - parseFloat(a.size)) 679 | .slice(0, 20); 680 | 681 | summary.addHeading('📦 Top 20 Largest Caches ' + (dryRun ? 'to Delete' : 'Deleted'), 3) 682 | .addTable([ 683 | [{data: 'Cache Key', header: true}, {data: 'Size (MB)', header: true}, {data: 'Age (days)', header: true}, {data: 'Type', header: true}], 684 | ...topCaches.map(c => [c.key, c.size, c.age.toString(), c.category]) 685 | ]); 686 | } 687 | 688 | // Add oldest caches 689 | if (deletedCaches.length > 0) { 690 | const oldestCaches = deletedCaches 691 | .sort((a, b) => b.age - a.age) 692 | .slice(0, 10); 693 | 694 | summary.addHeading('📅 Top 10 Oldest Caches ' + (dryRun ? 'to Delete' : 'Deleted'), 3) 695 | .addTable([ 696 | [{data: 'Cache Key', header: true}, {data: 'Age (days)', header: true}, {data: 'Size (MB)', header: true}, {data: 'Type', header: true}], 697 | ...oldestCaches.map(c => [c.key, c.age.toString(), c.size, c.category]) 698 | ]); 699 | } 700 | 701 | // Device breakdown for ccache deletions 702 | if (deletionStats.ccache.count > 0) { 703 | const deviceDeletions = new Map(); 704 | for (const cache of deletedCaches) { 705 | if (cache.category === 'ccache') { 706 | const match = cache.key.match(/ccache-([^-]+)-/); 707 | if (match) { 708 | const device = match[1]; 709 | if (!deviceDeletions.has(device)) { 710 | deviceDeletions.set(device, { count: 0, size: 0 }); 711 | } 712 | const data = deviceDeletions.get(device); 713 | data.count++; 714 | data.size += cache.sizeBytes; 715 | } 716 | } 717 | } 718 | 719 | if (deviceDeletions.size > 0) { 720 | const topDevices = Array.from(deviceDeletions.entries()) 721 | .sort((a, b) => b[1].size - a[1].size) 722 | .slice(0, 10); 723 | 724 | summary.addHeading('📱 Top 10 Devices by Deleted ccache', 3) 725 | .addTable([ 726 | [{data: 'Device', header: true}, {data: 'Caches', header: true}, {data: 'Size (GB)', header: true}], 727 | ...topDevices.map(([device, data]) => [ 728 | device, 729 | data.count.toString(), 730 | (data.size / 1024 / 1024 / 1024).toFixed(2) 731 | ]) 732 | ]); 733 | } 734 | } 735 | 736 | // Add failures if any 737 | if (skippedCaches.length > 0) { 738 | summary.addHeading('⚠️ Failed Deletions', 3) 739 | .addTable([ 740 | [{data: 'Cache Key', header: true}, {data: 'Reason', header: true}], 741 | ...skippedCaches.map(c => [c.key, c.reason]) 742 | ]); 743 | } 744 | 745 | summary.write(); 746 | 747 | cleanup-runs: 748 | runs-on: ubuntu-latest 749 | needs: analyze 750 | if: | 751 | always() && 752 | (inputs.cleanup_type == 'runs_only' || inputs.cleanup_type == 'full_cleanup') && 753 | (inputs.cleanup_type != 'analyze_only') 754 | 755 | steps: 756 | - name: 🗑️ Clean old workflow runs 757 | uses: actions/github-script@v7 758 | with: 759 | script: | 760 | const { owner, repo } = context.repo; 761 | const keepRecent = parseInt('${{ inputs.keep_recent_runs }}'); 762 | const daysToKeep = parseInt('${{ inputs.days_to_keep }}'); 763 | const dryRun = '${{ inputs.dry_run }}' === 'true'; 764 | const cutoffDate = new Date(); 765 | cutoffDate.setDate(cutoffDate.getDate() - daysToKeep); 766 | 767 | console.log(`📅 Configuration:`); 768 | console.log(` - Keeping runs from: ${cutoffDate.toISOString()}`); 769 | console.log(` - Keeping ${keepRecent} most recent successful runs per workflow`); 770 | console.log(` - Dry Run: ${dryRun}\n`); 771 | 772 | const workflows = await github.rest.actions.listRepoWorkflows({ 773 | owner, 774 | repo 775 | }); 776 | 777 | let totalDeleted = 0; 778 | let totalFailed = 0; 779 | const workflowStats = []; 780 | 781 | for (const workflow of workflows.data.workflows) { 782 | console.log(`\n📋 Processing: ${workflow.name}`); 783 | 784 | let page = 1; 785 | let successfulRuns = []; 786 | let deletedInWorkflow = 0; 787 | let failedInWorkflow = 0; 788 | 789 | const runsByStatus = { 790 | success: 0, 791 | failure: 0, 792 | cancelled: 0, 793 | skipped: 0, 794 | other: 0 795 | }; 796 | 797 | while (true) { 798 | const runs = await github.rest.actions.listWorkflowRuns({ 799 | owner, 800 | repo, 801 | workflow_id: workflow.id, 802 | per_page: 100, 803 | page: page 804 | }); 805 | 806 | if (runs.data.workflow_runs.length === 0) break; 807 | 808 | for (const run of runs.data.workflow_runs) { 809 | const runDate = new Date(run.created_at); 810 | const ageDays = Math.floor((new Date() - runDate) / (1000 * 60 * 60 * 24)); 811 | 812 | // Count by status 813 | runsByStatus[run.conclusion || 'other']++; 814 | 815 | // Track successful runs 816 | if (run.conclusion === 'success') { 817 | successfulRuns.push(run); 818 | } 819 | 820 | // Determine if should delete 821 | const isOld = runDate < cutoffDate; 822 | const isFailed = run.conclusion === 'failure'; 823 | const isCancelled = run.conclusion === 'cancelled'; 824 | const isSkipped = run.conclusion === 'skipped'; 825 | const tooManySuccessful = run.conclusion === 'success' && 826 | successfulRuns.length > keepRecent; 827 | 828 | const shouldDelete = 829 | (isFailed && isOld) || 830 | (isCancelled && isOld) || 831 | (isSkipped && isOld) || 832 | (tooManySuccessful && isOld); 833 | 834 | if (shouldDelete) { 835 | if (dryRun) { 836 | console.log(`🔍 Would delete: #${run.run_number} (${run.conclusion}, ${ageDays}d old)`); 837 | } else { 838 | console.log(`🗑️ Deleting: #${run.run_number} (${run.conclusion}, ${ageDays}d old)`); 839 | 840 | try { 841 | await github.rest.actions.deleteWorkflowRun({ 842 | owner, 843 | repo, 844 | run_id: run.id 845 | }); 846 | deletedInWorkflow++; 847 | totalDeleted++; 848 | } catch (error) { 849 | console.log(` ⚠️ Failed: ${error.message}`); 850 | failedInWorkflow++; 851 | totalFailed++; 852 | } 853 | } 854 | } 855 | } 856 | 857 | if (runs.data.workflow_runs.length < 100) break; 858 | page++; 859 | } 860 | 861 | if (deletedInWorkflow > 0 || Object.values(runsByStatus).some(v => v > 0)) { 862 | workflowStats.push({ 863 | name: workflow.name, 864 | deleted: deletedInWorkflow, 865 | failed: failedInWorkflow, 866 | stats: runsByStatus 867 | }); 868 | } 869 | } 870 | 871 | console.log(`\n✅ Total runs ${dryRun ? 'to delete' : 'deleted'}: ${totalDeleted}`); 872 | if (totalFailed > 0) { 873 | console.log(`⚠️ Failed deletions: ${totalFailed}`); 874 | } 875 | 876 | // Generate summary 877 | let summary = core.summary 878 | .addHeading(`🧹 Workflow Runs ${dryRun ? 'Preview' : 'Summary'}`) 879 | .addTable([ 880 | [{data: 'Metric', header: true}, {data: 'Value', header: true}], 881 | ['Runs ' + (dryRun ? 'to Delete' : 'Deleted'), totalDeleted.toString()], 882 | ['Failed Deletions', totalFailed.toString()], 883 | ['Kept Recent Successful', keepRecent.toString()], 884 | ['Days Kept', daysToKeep.toString()] 885 | ]); 886 | 887 | if (workflowStats.length > 0) { 888 | summary.addHeading('📊 Per-Workflow Breakdown', 3) 889 | .addTable([ 890 | [ 891 | {data: 'Workflow', header: true}, 892 | {data: 'Deleted', header: true}, 893 | {data: 'Success', header: true}, 894 | {data: 'Failure', header: true}, 895 | {data: 'Cancelled', header: true} 896 | ], 897 | ...workflowStats.map(w => [ 898 | w.name, 899 | w.deleted.toString(), 900 | w.stats.success.toString(), 901 | w.stats.failure.toString(), 902 | w.stats.cancelled.toString() 903 | ]) 904 | ]); 905 | } 906 | 907 | summary.write(); 908 | 909 | final-report: 910 | runs-on: ubuntu-latest 911 | needs: [analyze, cleanup-caches, cleanup-runs] 912 | if: always() 913 | 914 | steps: 915 | - name: 📊 Final Repository Health Report 916 | uses: actions/github-script@v7 917 | with: 918 | script: | 919 | const { owner, repo } = context.repo; 920 | const dryRun = '${{ inputs.dry_run }}' === 'true'; 921 | 922 | console.log('📊 Generating final health report...\n'); 923 | 924 | // Get current cache usage (after cleanup) 925 | let page = 1; 926 | let totalCacheSize = 0; 927 | let cachesByType = { 928 | ccache: 0, 929 | apt: 0, 930 | kernel: 0, 931 | other: 0 932 | }; 933 | let cacheCount = 0; 934 | const buildFrequency = new Map(); 935 | const recentCutoff = new Date(); 936 | recentCutoff.setDate(recentCutoff.getDate() - 30); 937 | 938 | while (true) { 939 | const res = await github.rest.actions.getActionsCacheList({ 940 | owner, 941 | repo, 942 | per_page: 100, 943 | page: page 944 | }); 945 | 946 | const caches = res.data.actions_caches; 947 | if (!caches || caches.length === 0) break; 948 | 949 | for (const cache of caches) { 950 | totalCacheSize += cache.size_in_bytes; 951 | cacheCount++; 952 | 953 | if (cache.key.startsWith('ccache-')) { 954 | cachesByType.ccache += cache.size_in_bytes; 955 | 956 | // Track build frequency 957 | const match = cache.key.match(/ccache-([^-]+)-/); 958 | if (match && new Date(cache.last_accessed_at) > recentCutoff) { 959 | const device = match[1]; 960 | buildFrequency.set(device, (buildFrequency.get(device) || 0) + 1); 961 | } 962 | } else if (cache.key.includes('apt')) { 963 | cachesByType.apt += cache.size_in_bytes; 964 | } else if (cache.key.includes('kernel') || cache.key.includes('android')) { 965 | cachesByType.kernel += cache.size_in_bytes; 966 | } else { 967 | cachesByType.other += cache.size_in_bytes; 968 | } 969 | } 970 | 971 | if (caches.length < 100) break; 972 | page++; 973 | } 974 | 975 | const totalGB = (totalCacheSize / 1024 / 1024 / 1024).toFixed(2); 976 | const ccacheGB = (cachesByType.ccache / 1024 / 1024 / 1024).toFixed(2); 977 | const aptGB = (cachesByType.apt / 1024 / 1024 / 1024).toFixed(2); 978 | const kernelGB = (cachesByType.kernel / 1024 / 1024 / 1024).toFixed(2); 979 | const otherGB = (cachesByType.other / 1024 / 1024 / 1024).toFixed(2); 980 | 981 | const limit = 10; // 10 GB 982 | const usagePercent = ((totalCacheSize / (limit * 1024 * 1024 * 1024)) * 100).toFixed(1); 983 | 984 | // Calculate change if we have before data 985 | const beforeSize = parseFloat('${{ needs.analyze.outputs.total_cache_size }}'); 986 | const beforeCount = parseInt('${{ needs.analyze.outputs.cache_count }}'); 987 | const beforePercent = parseFloat('${{ needs.analyze.outputs.usage_percent }}'); 988 | 989 | let changeInfo = ''; 990 | if (beforeSize > 0 && !dryRun) { 991 | const sizeChange = beforeSize - totalCacheSize; 992 | const countChange = beforeCount - cacheCount; 993 | const percentChange = beforePercent - parseFloat(usagePercent); 994 | 995 | const changeGB = (sizeChange / 1024 / 1024 / 1024).toFixed(2); 996 | 997 | changeInfo = `\n### 📈 Cleanup Impact\n\n` + 998 | `- **Space Freed:** ${changeGB} GB\n` + 999 | `- **Caches Removed:** ${countChange}\n` + 1000 | `- **Usage Reduced:** ${percentChange.toFixed(1)}%\n`; 1001 | } 1002 | 1003 | // Determine health status 1004 | let healthEmoji = '🟢'; 1005 | let healthStatus = 'Healthy'; 1006 | if (usagePercent > 90) { 1007 | healthEmoji = '🔴'; 1008 | healthStatus = 'Critical - Immediate Cleanup Needed!'; 1009 | } else if (usagePercent > 75) { 1010 | healthEmoji = '🟡'; 1011 | healthStatus = 'Warning - Consider Cleanup Soon'; 1012 | } 1013 | 1014 | let summary = core.summary 1015 | .addHeading(`${healthEmoji} Final Repository Health Report`) 1016 | .addRaw(dryRun ? '\n**⚠️ This was a DRY RUN - No changes were made**\n\n' : '\n') 1017 | .addTable([ 1018 | [{data: 'Cache Type', header: true}, {data: 'Size (GB)', header: true}, {data: 'Percentage', header: true}], 1019 | ['ccache (Kernel Builds)', ccacheGB, totalCacheSize > 0 ? `${((cachesByType.ccache / totalCacheSize) * 100).toFixed(1)}%` : '0%'], 1020 | ['Kernel-related', kernelGB, totalCacheSize > 0 ? `${((cachesByType.kernel / totalCacheSize) * 100).toFixed(1)}%` : '0%'], 1021 | ['APT Packages', aptGB, totalCacheSize > 0 ? `${((cachesByType.apt / totalCacheSize) * 100).toFixed(1)}%` : '0%'], 1022 | ['Other', otherGB, totalCacheSize > 0 ? `${((cachesByType.other / totalCacheSize) * 100).toFixed(1)}%` : '0%'], 1023 | ['**Total**', `**${totalGB}**`, '**100%**'] 1024 | ]) 1025 | .addRaw(`\n### 📊 Current Usage Statistics\n\n`) 1026 | .addRaw(`- **Total Caches:** ${cacheCount}\n`) 1027 | .addRaw(`- **Limit:** ${limit} GB\n`) 1028 | .addRaw(`- **Current Usage:** ${totalGB} GB (${usagePercent}%)\n`) 1029 | .addRaw(`- **Available:** ${(limit - parseFloat(totalGB)).toFixed(2)} GB\n`) 1030 | .addRaw(`- **Status:** ${healthStatus}\n`) 1031 | .addRaw(changeInfo); 1032 | 1033 | // Build activity analysis 1034 | if (buildFrequency.size > 0) { 1035 | const activeDevices = Array.from(buildFrequency.entries()) 1036 | .filter(([_, count]) => count >= 3) 1037 | .sort((a, b) => b[1] - a[1]); 1038 | 1039 | summary.addRaw(`\n### 📱 Build Activity Analysis (Last 30 Days)\n\n`) 1040 | .addRaw(`- **Active Devices:** ${activeDevices.length}\n`) 1041 | .addRaw(`- **Total Build Events:** ${Array.from(buildFrequency.values()).reduce((a, b) => a + b, 0)}\n`); 1042 | 1043 | if (activeDevices.length > 0) { 1044 | const topActive = activeDevices.slice(0, 10); 1045 | summary.addRaw(`\n**Top 10 Most Active Devices:**\n`) 1046 | .addTable([ 1047 | [{data: 'Device', header: true}, {data: 'Build Events', header: true}], 1048 | ...topActive.map(([device, count]) => [device, count.toString()]) 1049 | ]); 1050 | } 1051 | } 1052 | 1053 | summary.addRaw(`\n### 💡 Next Steps\n\n`); 1054 | 1055 | if (dryRun) { 1056 | summary.addRaw(`- ℹ️ This was a dry run - run again with \`dry_run: false\` to apply changes\n`); 1057 | } else if (parseFloat(usagePercent) > 75) { 1058 | summary.addRaw(`- ⚠️ **Action Required:** Usage still high, consider additional cleanup\n`) 1059 | .addRaw(`- Target specific devices or cache types\n`) 1060 | .addRaw(`- Review ccache size limits\n`); 1061 | } else { 1062 | summary.addRaw(`- ✅ Cache usage is now healthy\n`) 1063 | .addRaw(`- Schedule regular cleanup (weekly recommended)\n`) 1064 | .addRaw(`- Monitor usage trends\n`); 1065 | } 1066 | 1067 | summary.addRaw(`\n### 🔄 Cleanup Schedule Recommendations\n\n`) 1068 | .addRaw(`- **Daily:** If building > 10 devices regularly\n`) 1069 | .addRaw(`- **Weekly:** For moderate usage (5-10 devices)\n`) 1070 | .addRaw(`- **Monthly:** For light usage (< 5 devices)\n`) 1071 | .addRaw(`- **On-demand:** When usage exceeds 75%\n`); 1072 | 1073 | summary.write(); 1074 | 1075 | console.log(`\n✅ Final report generated`); 1076 | console.log(` - Current usage: ${totalGB} GB (${usagePercent}%)`); 1077 | console.log(` - Status: ${healthStatus}`); 1078 | 1079 | - name: 💡 Quick Action Commands 1080 | if: always() 1081 | run: | 1082 | cat >> $GITHUB_STEP_SUMMARY << 'EOF' 1083 | 1084 | --- 1085 | 1086 | ## 🚀 Quick Action Commands 1087 | 1088 | ### High Usage Cleanup (>75%) 1089 | ```bash 1090 | # Clean all old caches (>7 days) 1091 | gh workflow run cleanup.yml \ 1092 | -f cleanup_type=cache_only \ 1093 | -f cache_pattern=old_only \ 1094 | -f cache_age_days=7 1095 | 1096 | # Clean stale ccache (>14 days) 1097 | gh workflow run cleanup.yml \ 1098 | -f cleanup_type=cache_only \ 1099 | -f cache_pattern=ccache_stale 1100 | 1101 | # Clean specific device 1102 | gh workflow run cleanup.yml \ 1103 | -f cleanup_type=cache_only \ 1104 | -f device_filter=OP13 \ 1105 | -f cache_pattern=ccache_only 1106 | ``` 1107 | 1108 | ### Regular Maintenance 1109 | ```bash 1110 | # Weekly cleanup (recommended) 1111 | gh workflow run cleanup.yml \ 1112 | -f cleanup_type=full_cleanup \ 1113 | -f cache_age_days=14 1114 | 1115 | # Analyze only (no changes) 1116 | gh workflow run cleanup.yml \ 1117 | -f cleanup_type=analyze_only 1118 | 1119 | # Dry run preview 1120 | gh workflow run cleanup.yml \ 1121 | -f cleanup_type=cache_only \ 1122 | -f dry_run=true 1123 | ``` 1124 | 1125 | ### Emergency Cleanup 1126 | ```bash 1127 | # Force cleanup everything old 1128 | gh workflow run cleanup.yml \ 1129 | -f cleanup_type=full_cleanup \ 1130 | -f force_cleanup=true \ 1131 | -f cache_age_days=3 1132 | 1133 | # Clean all ccache immediately 1134 | gh workflow run cleanup.yml \ 1135 | -f cleanup_type=cache_only \ 1136 | -f cache_pattern=ccache_only \ 1137 | -f force_cleanup=true 1138 | ``` 1139 | 1140 | ### Device-Specific Cleanup 1141 | ```bash 1142 | # Clean by kernel version 1143 | gh workflow run cleanup.yml \ 1144 | -f cleanup_type=cache_only \ 1145 | -f device_filter=android15-6.6 \ 1146 | -f cache_pattern=ccache_only 1147 | 1148 | # Clean specific phone model 1149 | gh workflow run cleanup.yml \ 1150 | -f cleanup_type=cache_only \ 1151 | -f device_filter=OP13 \ 1152 | -f cache_pattern=all_caches 1153 | ``` 1154 | 1155 | ### Workflow Runs Cleanup 1156 | ```bash 1157 | # Clean old workflow runs 1158 | gh workflow run cleanup.yml \ 1159 | -f cleanup_type=runs_only \ 1160 | -f days_to_keep=7 \ 1161 | -f keep_recent_runs=3 1162 | ``` 1163 | 1164 | --- 1165 | 1166 | **💡 Tip:** Use `dry_run=true` first to preview what will be deleted! 1167 | 1168 | EOF 1169 | --------------------------------------------------------------------------------