├── 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 | | :warning: |
7 | All the Kernels are built on OnePlus Official Source and are expected to work only on Stock roms!!! |
8 |
9 |
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 | | :warning: |
19 | 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. |
20 |
21 |
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 | | Device Name |
30 | Working Kernel Device Name |
31 | Current Kernel Version |
32 |
33 |
34 | | Poco X7 Pro |
35 | OnePlus 13 OnePlus Ace 5 Pro |
36 | android15-6.6.30 android15-6.6.30 |
37 |
38 |
39 | Realme GT Neo 5SE Realme GT Neo 5 |
40 | OnePlus 10T OnePlus 10 Pro OnePlus Ace 2 OnePlus 11r (Partially) |
41 | android12-5.10.209 android12-5.10.209 android12-5.10.209 android12-5.10.209 |
42 |
43 |
44 | | Realme GT 5 |
45 | OnePlus 11 |
46 | android13-5.15.149 |
47 |
48 |
49 | Realme GT Neo 6SE Realme GT Neo 6T |
50 | OnePlus Nord 4 |
51 | android14-6.1.75 |
52 |
53 |
54 | | Realme GT 2 Pro |
55 | OnePlus 10 Pro |
56 | android12-5.10.209 |
57 |
58 |
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 | | :warning: |
18 | Verify Compatibility of kernels before flashing. |
19 |
20 |
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 |
--------------------------------------------------------------------------------