Skip to content

Commit 941caa9

Browse files
committed
feat: provide standalone binaries via tag-based release workflow
Replaces manual release + separate homebrew update with a single tag-push trigger (git tag vX.Y.Z && git push origin vX.Y.Z) that: - Builds standalone binaries for Linux x86_64, macOS x86_64, macOS ARM64, and Windows x86_64 via PyInstaller - Creates a GitHub Release with auto-extracted changelog notes and per-platform checksums - Updates the Homebrew tap formula Closes #46
1 parent 6a06a5c commit 941caa9

4 files changed

Lines changed: 177 additions & 44 deletions

File tree

.github/workflows/release.yml

Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
name: Release
2+
3+
on:
4+
push:
5+
tags:
6+
- 'v*.*.*'
7+
8+
jobs:
9+
# ──────────────────────────────────────────
10+
# 1. Build binaries for all platforms
11+
# ──────────────────────────────────────────
12+
build:
13+
name: Build binary (${{ matrix.os }})
14+
runs-on: ${{ matrix.os }}
15+
strategy:
16+
fail-fast: false
17+
matrix:
18+
include:
19+
- os: ubuntu-latest
20+
asset_name: gitfetch-linux-x86_64
21+
- os: macos-13
22+
asset_name: gitfetch-macos-x86_64
23+
- os: macos-latest
24+
asset_name: gitfetch-macos-arm64
25+
- os: windows-latest
26+
asset_name: gitfetch-windows-x86_64.exe
27+
28+
steps:
29+
- name: Checkout repository
30+
uses: actions/checkout@v4
31+
32+
- name: Set up Python 3.12
33+
uses: actions/setup-python@v5
34+
with:
35+
python-version: "3.12"
36+
37+
- name: Install dependencies
38+
run: |
39+
python -m pip install --upgrade pip
40+
pip install -r requirements.txt
41+
pip install pyinstaller
42+
pip install -e .
43+
44+
- name: Build binary with PyInstaller
45+
run: |
46+
pyinstaller \
47+
--onefile \
48+
--name ${{ matrix.asset_name }} \
49+
--distpath ./dist \
50+
--paths src \
51+
--hidden-import readchar \
52+
--hidden-import webcolors \
53+
--hidden-import requests \
54+
--copy-metadata readchar \
55+
--copy-metadata webcolors \
56+
--copy-metadata requests \
57+
run.py
58+
59+
- name: Upload artifact
60+
uses: actions/upload-artifact@v4
61+
with:
62+
name: ${{ matrix.asset_name }}
63+
path: ./dist/${{ matrix.asset_name }}*
64+
65+
# ──────────────────────────────────────────
66+
# 2. Create GitHub Release and attach assets
67+
# ──────────────────────────────────────────
68+
release:
69+
name: Create Release
70+
needs: build
71+
runs-on: ubuntu-latest
72+
permissions:
73+
contents: write
74+
75+
steps:
76+
- name: Checkout repository
77+
uses: actions/checkout@v4
78+
with:
79+
fetch-depth: 0
80+
81+
- name: Get version from tag
82+
id: version
83+
run: |
84+
VERSION=${GITHUB_REF_NAME#v}
85+
echo "version=$VERSION" >> $GITHUB_OUTPUT
86+
echo "tag=$GITHUB_REF_NAME" >> $GITHUB_OUTPUT
87+
88+
- name: Download all binary artifacts
89+
uses: actions/download-artifact@v4
90+
with:
91+
path: ./dist
92+
93+
- name: Generate checksums
94+
run: |
95+
cd ./dist
96+
find . -type f -exec shasum -a 256 {} \; > checksums.txt
97+
cd ..
98+
99+
- name: Generate release notes
100+
id: notes
101+
run: |
102+
if [ -f CHANGELOG.md ]; then
103+
awk '/^## \[Unreleased\]/{flag=1; next} /^## \[/{flag=0} flag' CHANGELOG.md \
104+
| sed '/./,$!d' > release_body.md
105+
fi
106+
if [ ! -s release_body.md ]; then
107+
echo "No unreleased changelog entries found. Using default."
108+
echo "## gitfetch v${{ steps.version.outputs.version }}" > release_body.md
109+
echo "" >> release_body.md
110+
echo "See [CHANGELOG.md](https://github.com/${{ github.repository }}/blob/main/CHANGELOG.md) for details." >> release_body.md
111+
fi
112+
echo "body<<EOF" >> $GITHUB_OUTPUT
113+
cat release_body.md >> $GITHUB_OUTPUT
114+
echo "EOF" >> $GITHUB_OUTPUT
115+
116+
- name: Create Release
117+
uses: softprops/action-gh-release@v2
118+
with:
119+
tag_name: ${{ steps.version.outputs.tag }}
120+
name: v${{ steps.version.outputs.version }}
121+
body: ${{ steps.notes.outputs.body }}
122+
files: |
123+
./dist/*/gitfetch-*
124+
./dist/checksums.txt
125+
fail_on_unmatched_files: false
126+
127+
# ──────────────────────────────────────────
128+
# 3. Update Homebrew tap
129+
# ──────────────────────────────────────────
130+
update-homebrew:
131+
name: Update Homebrew Tap
132+
needs: release
133+
runs-on: ubuntu-latest
134+
if: ${{ vars.HOMEBREW_TAP_REPO != '' }}
135+
steps:
136+
- name: Checkout main repo
137+
uses: actions/checkout@v4
138+
with:
139+
path: gitfetch
140+
141+
- name: Get version from tag
142+
id: version
143+
run: |
144+
VERSION=${GITHUB_REF_NAME#v}
145+
echo "version=$VERSION" >> $GITHUB_OUTPUT
146+
147+
- name: Checkout tap repo
148+
uses: actions/checkout@v4
149+
with:
150+
repository: ${{ vars.HOMEBREW_TAP_REPO }}
151+
token: ${{ secrets.HOMEBREW_TAP_TOKEN }}
152+
path: homebrew-tap
153+
154+
- name: Update formula
155+
run: |
156+
cd homebrew-tap
157+
chmod +x .github/scripts/update-homebrew.sh
158+
VERSION=${{ steps.version.outputs.version }} ./.github/scripts/update-homebrew.sh
159+
160+
- name: Commit and push
161+
run: |
162+
cd homebrew-tap
163+
git config user.name "github-actions[bot]"
164+
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
165+
git add Formula/gitfetch.rb
166+
git commit -m "Update gitfetch to v${{ steps.version.outputs.version }}"
167+
git push

.github/workflows/update-homebrew.yml

Lines changed: 0 additions & 44 deletions
This file was deleted.

.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,11 @@ __pycache__/
1010
*.egg-info
1111

1212

13+
# PyInstaller
14+
*.spec
15+
dist/
16+
build/
17+
1318
# env
1419
venv/
1520
.venv

run.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
"""Entry point for PyInstaller binary builds."""
2+
from gitfetch.cli import main
3+
4+
if __name__ == "__main__":
5+
main()

0 commit comments

Comments
 (0)