@@ -26,15 +26,83 @@ jobs:
2626 VERSION="${{ github.event.inputs.version }}"
2727 fi
2828 echo "VERSION=$VERSION" >> $GITHUB_ENV
29+ echo "Building Homebrew formula for version: $VERSION"
2930
30- - name : Get PyPI package info and SHA256
31+ - name : Wait and get PyPI package info with retry
3132 run : |
32- # Corrected URL to download the source package from PyPI
33- wget "https://pypi.org/packages/source/o/omnipkg/omnipkg-${{ env.VERSION }}.tar.gz"
33+ # --- RESILIENT RETRY LOGIC FOR PYPI AVAILABILITY ---
34+ max_attempts=15
35+ attempt=1
36+ url="https://pypi.org/packages/source/o/omnipkg/omnipkg-${{ env.VERSION }}.tar.gz"
37+
38+ echo "🔍 Waiting for PyPI package to be available at: $url"
39+ echo "⏳ This may take a few minutes after release publication..."
40+
41+ # Initial wait before first attempt (PyPI needs time to process)
42+ echo "💤 Initial wait of 60 seconds for PyPI processing..."
43+ sleep 60
44+
45+ while [ $attempt -le $max_attempts ]; do
46+ echo "🚀 Attempt $attempt of $max_attempts..."
47+
48+ # Try to download with curl (more reliable than wget)
49+ if curl -L --fail --connect-timeout 30 --max-time 300 -o "omnipkg-${{ env.VERSION }}.tar.gz" "$url"; then
50+ echo "✅ Successfully downloaded package on attempt $attempt!"
51+
52+ # Verify the file is actually valid (not an error page)
53+ file_size=$(wc -c < "omnipkg-${{ env.VERSION }}.tar.gz")
54+ echo "📦 Downloaded file size: $file_size bytes"
55+
56+ if [ "$file_size" -gt 1000 ]; then
57+ echo "✅ File size looks good, proceeding..."
58+ break
59+ else
60+ echo "⚠️ File too small ($file_size bytes), might be error page. Retrying..."
61+ rm -f "omnipkg-${{ env.VERSION }}.tar.gz"
62+ fi
63+ else
64+ echo "❌ Download failed on attempt $attempt"
65+ fi
66+
67+ if [ $attempt -lt $max_attempts ]; then
68+ wait_time=$((30 + attempt * 10)) # Progressive backoff: 40s, 50s, 60s, etc.
69+ echo "⏰ Waiting $wait_time seconds before retry..."
70+ sleep $wait_time
71+ fi
72+
73+ attempt=$((attempt + 1))
74+ done
75+
76+ if [ $attempt -gt $max_attempts ]; then
77+ echo "💥 FAILED: Package not available on PyPI after $max_attempts attempts"
78+ echo "🤔 This might mean:"
79+ echo " - PyPI is still processing the release"
80+ echo " - The package failed to upload to PyPI"
81+ echo " - There's a network issue"
82+ echo ""
83+ echo "🔧 Try running this workflow manually in a few minutes with workflow_dispatch"
84+ exit 1
85+ fi
86+
87+ # Calculate SHA256 using a more reliable method
88+ echo "🔐 Calculating SHA256 hash..."
89+ if command -v sha256sum >/dev/null 2>&1; then
90+ SHA256=$(sha256sum "omnipkg-${{ env.VERSION }}.tar.gz" | cut -d' ' -f1)
91+ else
92+ # Fallback for systems without sha256sum
93+ SHA256=$(python3 -c "
94+ import hashlib
95+ with open('omnipkg-${{ env.VERSION }}.tar.gz', 'rb') as f:
96+ content = f.read()
97+ print(hashlib.sha256(content).hexdigest())
98+ ")
99+ fi
34100
35- SHA256=$(sha256sum "omnipkg-${{ env.VERSION }}.tar.gz" | cut -d' ' -f1)
36101 echo "SHA256=$SHA256" >> $GITHUB_ENV
37- echo "Downloaded omnipkg-${{ env.VERSION }}.tar.gz with SHA256: $SHA256"
102+ echo "✅ Package SHA256: $SHA256"
103+
104+ # Clean up the downloaded file
105+ rm -f "omnipkg-${{ env.VERSION }}.tar.gz"
38106
39107 - name : Checkout Homebrew tap
40108 uses : actions/checkout@v4
@@ -43,36 +111,69 @@ jobs:
43111 token : ${{ secrets.HOMEBREW_TAP_TOKEN }}
44112 path : homebrew-tap
45113
46- - name : Update formula
114+ - name : Update main formula
47115 run : |
48116 cd homebrew-tap
49117
50- # Update the formula file
51- sed -i 's|url "https://pypi.io/packages/source/o/omnipkg/omnipkg-.*\.tar\.gz"|url "https://pypi.org/packages/source/o/omnipkg/omnipkg-${{ env.VERSION }}.tar.gz"|' omnipkg.rb
118+ if [ ! -f "omnipkg.rb" ]; then
119+ echo "❌ Formula file omnipkg.rb not found!"
120+ exit 1
121+ fi
122+
123+ echo "🔧 Updating omnipkg formula..."
124+
125+ # Update the main package URL and SHA256
126+ # Handle both possible URL formats
127+ sed -i 's|url "https://pypi\.io/packages/source/o/omnipkg/omnipkg-.*\.tar\.gz"|url "https://pypi.org/packages/source/o/omnipkg/omnipkg-${{ env.VERSION }}.tar.gz"|' omnipkg.rb
128+ sed -i 's|url "https://pypi\.org/packages/source/o/omnipkg/omnipkg-.*\.tar\.gz"|url "https://pypi.org/packages/source/o/omnipkg/omnipkg-${{ env.VERSION }}.tar.gz"|' omnipkg.rb
52129 sed -i 's/sha256 ".*"/sha256 "${{ env.SHA256 }}"/' omnipkg.rb
53130
54- echo "=== Updated formula ==="
55- head -10 omnipkg.rb
131+ echo "=== Updated main formula section ==="
132+ head -15 omnipkg.rb
56133
57- - name : Get latest dependency versions and hashes
134+ - name : Update dependency versions and hashes
58135 run : |
59136 cd homebrew-tap
137+
138+ echo "🔍 Updating dependency versions..."
139+
60140 python3 << 'EOF'
61141 import json
62142 import urllib.request
63143 import re
64- # Dependencies to update (from your current formula)
144+ import time
145+ import sys
146+ from urllib.error import HTTPError, URLError
147+
148+ # Dependencies to update
65149 deps = [
66150 "aiohappyeyeballs", "aiohttp", "aiosignal", "attrs", "certifi",
67151 "charset-normalizer", "filelock", "frozenlist", "idna", "multidict",
68152 "packaging", "propcache", "python-magic", "redis", "requests",
69153 "tqdm", "typing-extensions", "urllib3", "yarl"
70154 ]
71- formula_content = open('omnipkg.rb', 'r').read()
72- for dep in deps:
155+
156+ print(f"📋 Updating {len(deps)} dependencies...")
157+
158+ try:
159+ with open('omnipkg.rb', 'r') as f:
160+ formula_content = f.read()
161+ except FileNotFoundError:
162+ print("❌ Error: omnipkg.rb not found!")
163+ sys.exit(1)
164+
165+ updated_count = 0
166+ failed_count = 0
167+
168+ for i, dep in enumerate(deps, 1):
169+ print(f"🔄 [{i}/{len(deps)}] Processing {dep}...")
170+
73171 try:
74- # Get latest version from PyPI API
75- with urllib.request.urlopen(f'https://pypi.org/pypi/{dep}/json') as response:
172+ # Add small delay to be nice to PyPI API
173+ if i > 1:
174+ time.sleep(0.5)
175+
176+ with urllib.request.urlopen(f'https://pypi.org/pypi/{dep}/json', timeout=30) as response:
76177 data = json.loads(response.read())
77178 latest_version = data['info']['version']
78179
@@ -86,31 +187,103 @@ jobs:
86187 break
87188
88189 if sdist_url and sha256_hash:
89- print(f"Updating {dep} to {latest_version}")
190+ print(f" ✅ Found {dep} v {latest_version}")
90191
91- # Update the resource block
92- pattern = f'(resource "{dep}" do.*?url ")(.*?)(".*?sha256 ")(.*?)(")'
192+ # Update the resource block with more robust regex
193+ pattern = f'(resource "{re.escape( dep) }" do.*?url ")(.*?)(".*?sha256 ")(.*?)(")'
93194 replacement = f'\\g<1>{sdist_url}\\g<3>{sha256_hash}\\g<5>'
195+
196+ old_formula = formula_content
94197 formula_content = re.sub(pattern, replacement, formula_content, flags=re.DOTALL)
198+
199+ if formula_content != old_formula:
200+ updated_count += 1
201+ print(f" 📝 Updated {dep}")
202+ else:
203+ print(f" ⚠️ Pattern not found for {dep} (might already be current)")
204+ else:
205+ print(f" ⚠️ No source distribution found for {dep}")
206+ failed_count += 1
95207
208+ except (HTTPError, URLError) as e:
209+ print(f" ❌ HTTP error for {dep}: {e}")
210+ failed_count += 1
211+ except json.JSONDecodeError as e:
212+ print(f" ❌ JSON decode error for {dep}: {e}")
213+ failed_count += 1
96214 except Exception as e:
97- print(f"Warning: Could not update {dep}: {e}")
215+ print(f" ❌ Unexpected error for {dep}: {e}")
216+ failed_count += 1
217+
98218 # Write the updated formula
99- with open('omnipkg.rb', 'w') as f:
100- f.write(formula_content)
219+ try:
220+ with open('omnipkg.rb', 'w') as f:
221+ f.write(formula_content)
222+ print(f"📊 Summary: {updated_count} updated, {failed_count} failed")
223+ except Exception as e:
224+ print(f"❌ Error writing formula: {e}")
225+ sys.exit(1)
101226 EOF
102227
228+ - name : Verify updated formula
229+ run : |
230+ cd homebrew-tap
231+
232+ echo "🔍 Verifying updated formula..."
233+ echo "=== First 30 lines of updated formula ==="
234+ head -30 omnipkg.rb
235+
236+ echo ""
237+ echo "=== Checking for obvious issues ==="
238+
239+ # Basic syntax checks
240+ if grep -q 'sha256 ""' omnipkg.rb; then
241+ echo "❌ Found empty SHA256 - this will cause issues!"
242+ exit 1
243+ fi
244+
245+ if grep -q 'url ""' omnipkg.rb; then
246+ echo "❌ Found empty URL - this will cause issues!"
247+ exit 1
248+ fi
249+
250+ echo "✅ Basic validation passed"
251+
103252 - name : Commit and push changes
104253 run : |
105254 cd homebrew-tap
255+
256+ # Configure git
106257 git config --local user.email "action@github.com"
107- git config --local user.name "GitHub Action"
108- git add omnipkg.rb
258+ git config --local user.name "GitHub Action Bot"
109259
110- if git diff --staged --quiet; then
111- echo "No changes to commit"
112- else
113- git commit -m "Update omnipkg to version ${{ env.VERSION }}"
114- git push
115- echo "Successfully updated Homebrew formula to version ${{ env.VERSION }}"
260+ # Check if there are any changes
261+ if git diff --quiet omnipkg.rb; then
262+ echo "ℹ️ No changes detected in omnipkg.rb"
263+ exit 0
116264 fi
265+
266+ echo "📝 Changes detected, committing..."
267+ git add omnipkg.rb
268+
269+ # Create detailed commit message
270+ commit_msg="Update omnipkg to version ${{ env.VERSION }}
271+
272+ - Updated main package to v${{ env.VERSION }}
273+ - Updated SHA256 hash: ${{ env.SHA256 }}
274+ - Refreshed dependency versions from PyPI
275+
276+ Auto-generated by GitHub Actions"
277+
278+ git commit -m "$commit_msg"
279+
280+ echo "🚀 Pushing changes to homebrew tap..."
281+ git push
282+
283+ echo "🎉 Successfully updated Homebrew formula to version ${{ env.VERSION }}!"
284+ echo ""
285+ echo "🍺 Users can now install with:"
286+ echo " brew install 1minds3t/omnipkg/omnipkg"
287+ echo ""
288+ echo "🔄 Or update existing installations with:"
289+ echo " brew upgrade omnipkg"
0 commit comments