1+ name : Mirror clang to GitHub Release
2+
3+ permissions :
4+ contents : write
5+
6+ on :
7+ workflow_dispatch :
8+
9+ jobs :
10+ prepare-release :
11+ runs-on : ubuntu-latest
12+ steps :
13+ - name : Ensure Single Release
14+ env :
15+ GH_TOKEN : ${{ secrets.GITHUB_TOKEN }}
16+ run : |
17+ # Create the release once. If it exists, it fails safely.
18+ gh release create "source-cache" \
19+ --title "Source Mirror Cache" \
20+ --notes "Deduplicated Clang Toolchains" \
21+ --draft \
22+ --repo "${{ github.repository }}" || echo "Release already exists."
23+
24+ generate-mirror-matrix :
25+ runs-on : ubuntu-latest
26+ needs : prepare-release
27+ outputs :
28+ matrix : ${{ steps.set-matrix.outputs.matrix }}
29+ steps :
30+ - name : 📥 Checkout Code
31+ uses : actions/checkout@v6
32+
33+ - name : 🔍 Generate Mirror Matrix
34+ id : generate-config
35+ shell : bash
36+ run : |
37+ set -euo pipefail
38+
39+ echo "[" > all_configs.json
40+ mapfile -t files < <(find configs/ -name "*.json")
41+ for i in "${!files[@]}"; do
42+ cat "${files[$i]}" >> all_configs.json
43+ [[ $((i+1)) -lt ${#files[@]} ]] && echo "," >> all_configs.json
44+ done
45+ echo "]" >> all_configs.json
46+
47+ - name : 🔍 Resolve Unique Projects
48+ id : set-matrix
49+ shell : python
50+ env :
51+ PYTHONUNBUFFERED : " 1"
52+ run : |
53+ import xml.etree.ElementTree as ET
54+ import json
55+ import os
56+ import subprocess
57+ import shutil
58+
59+ with open('all_configs.json', 'r') as f:
60+ configs = json.load(f)
61+
62+ unique_clang = {}
63+ seen_count = 0
64+
65+ print(f"🧐 Processing {len(configs)} configurations...")
66+ print("-" * 50)
67+
68+ for cfg in configs:
69+ op_model = cfg.get('model', 'Unknown')
70+ op_branch = cfg.get('branch', '')
71+ op_manifest = cfg.get('manifest', '')
72+ op_os_version = cfg.get('os_version', '').lower()
73+
74+ xml_file = "temp_manifest.xml"
75+
76+ try:
77+ if op_manifest.startswith("https://"):
78+ subprocess.run(f"curl -LfsS {op_manifest} -o {xml_file}", shell=True, check=True)
79+ elif op_branch.startswith("wild/"):
80+ shutil.copy(f"manifests/{op_os_version}/{op_manifest}", xml_file)
81+ else:
82+ url = f"https://raw.githubusercontent.com/OnePlusOSS/kernel_manifest/refs/heads/{op_branch}/{op_manifest}"
83+ subprocess.run(f"curl -LfsS {url} -o {xml_file}", shell=True, check=True)
84+
85+ root = ET.parse(xml_file).getroot()
86+ remotes = {r.get('name'): r.get('fetch').rstrip('/') for r in root.findall('remote')}
87+ default = root.find('default')
88+ def_remote = default.get('remote')
89+ def_rev = default.get('revision')
90+
91+ for project in root.findall('project'):
92+ name = project.get('name')
93+ if "clang" in name.lower():
94+ remote_name = project.get('remote', def_remote)
95+ rev = project.get('revision', def_rev)
96+ base_url = remotes.get(remote_name, "")
97+
98+ if rev not in unique_clang and ("git.codelinaro.org" in base_url or "googlesource.com" in base_url):
99+ if "googlesource.com" in base_url:
100+ dl_url = f"{base_url}/{name}/+archive/{rev}.tar.gz"
101+ else:
102+ dl_url = f"{base_url}/{name}/-/archive/{rev}.tar.gz"
103+ unique_clang[rev] = {"rev": rev, "url": dl_url, "name": name}
104+ print(f"🆕 [{op_model}][{op_os_version}] -> New Clang found: {rev}")
105+ else:
106+ print(f"♻️ [{op_model}][{op_os_version}] -> Using existing Clang: {rev}")
107+ except Exception as e:
108+ print(f"⚠️ Failed to process {op_manifest}: {e}")
109+ matrix = {"include": list(unique_clang.values())}
110+ with open(os.environ['GITHUB_OUTPUT'], 'a') as f:
111+ f.write(f"matrix={json.dumps(matrix)}\n")
112+ print(f"✅ Found {len(unique_clang)} unique projects to mirror.")
113+
114+ mirror-to-release :
115+ needs : [prepare-release, generate-mirror-matrix]
116+ runs-on : ubuntu-latest
117+ strategy :
118+ fail-fast : false
119+ matrix : ${{ fromJSON(needs.generate-mirror-matrix.outputs.matrix) }}
120+ env :
121+ GH_TOKEN : ${{ secrets.GITHUB_TOKEN }}
122+ steps :
123+ - name : 🚀 Sync & Upload
124+ run : |
125+ TARGET_REPO="${{ github.repository }}"
126+ REV="${{ matrix.rev }}"
127+ FILENAME="${REV}.tar.gz
128+
129+ # Check cache
130+ HTTP_STATUS=$(curl -I -s -o /dev/null -w "%{http_code}" -L \
131+ -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
132+ "https://github.com/${{ github.repository }}/releases/download/source-cache/${REV}.tar.gz")
133+
134+ if [ "$HTTP_STATUS" != "302" ] && [ "$HTTP_STATUS" != "200" ]; then
135+ echo "📥 Downloading Clang: ${{ matrix.name }}..."
136+ curl -LfsS -H 'User-Agent: Mozilla/5.0' --tcp-fastopen -o "$FILENAME" "${{ matrix.url }}"
137+
138+ FILE_SIZE=$(stat -c%s "$FILENAME")
139+ MAX_SIZE=2000000000 # ~1.86GB
140+
141+ if [ "$FILE_SIZE" -gt "$MAX_SIZE" ]; then
142+ echo "⚠️ File is > 2GB ($FILE_SIZE bytes). Splitting..."
143+ split -b 1500M "$FILENAME" "${FILENAME}.part"
144+
145+ for part in ${FILENAME}.part*; do
146+ echo "📤 Uploading $part..."
147+ gh release upload "source-cache" "$part" --clobber --repo "$TARGET_REPO"
148+ done
149+ else
150+ echo "📤 Uploading single file..."
151+ gh release upload "source-cache" "$FILENAME" --clobber --repo "$TARGET_REPO"
152+ fi
153+ else
154+ echo "✅ Clang revision ${{ matrix.rev }} already cached."
155+ fi
0 commit comments