|
1 | | -name: Build Bangen (Nuitka) |
| 1 | +name: Build & Release Bangen |
2 | 2 |
|
3 | 3 | on: |
| 4 | + workflow_dispatch: |
4 | 5 | push: |
5 | 6 | tags: |
6 | | - - "v*" |
7 | | - workflow_dispatch: |
| 7 | + - "*.*.*" |
8 | 8 |
|
9 | | -permissions: |
10 | | - contents: write |
| 9 | +concurrency: |
| 10 | + group: release-${{ github.ref }} |
| 11 | + cancel-in-progress: true |
11 | 12 |
|
12 | 13 | jobs: |
13 | | - # --- Tagging Job --- |
14 | | - # Ensures a version tag exists based on pyproject.toml if triggered from a branch |
15 | | - tag: |
16 | | - if: github.ref_type == 'branch' |
17 | | - runs-on: ubuntu-latest |
18 | | - outputs: |
19 | | - version: ${{ steps.version.outputs.VERSION }} |
20 | | - steps: |
21 | | - - uses: actions/checkout@v4 |
22 | | - with: |
23 | | - fetch-depth: 0 |
24 | | - |
25 | | - - name: Extract version |
26 | | - id: version |
27 | | - run: | |
28 | | - VERSION=$(python - <<EOF |
29 | | - import tomllib, pathlib |
30 | | - data = tomllib.loads(pathlib.Path("pyproject.toml").read_text()) |
31 | | - print(data["project"]["version"]) |
32 | | - EOF |
33 | | - ) |
34 | | - echo "VERSION=$VERSION" >> $GITHUB_OUTPUT |
35 | | -
|
36 | | - - name: Create tag if missing |
37 | | - run: | |
38 | | - TAG_NAME="v${{ steps.version.outputs.VERSION }}" |
39 | | - if git rev-parse "$TAG_NAME" >/dev/null 2>&1; then |
40 | | - echo "Tag $TAG_NAME already exists." |
41 | | - else |
42 | | - git config user.name "github-actions" |
43 | | - git config user.email "github-actions@github.com" |
44 | | - git tag "$TAG_NAME" |
45 | | - git push origin "$TAG_NAME" |
46 | | - fi |
47 | | -
|
48 | | - # --- Build Job --- |
49 | | - # Compiles the application into a single executable for Linux, macOS, and Windows |
50 | 14 | build: |
51 | | - needs: tag |
| 15 | + name: Build (${{ matrix.name }}) |
| 16 | + runs-on: ${{ matrix.os }} |
| 17 | + |
52 | 18 | strategy: |
53 | 19 | fail-fast: false |
54 | 20 | matrix: |
55 | 21 | include: |
56 | 22 | - os: ubuntu-latest |
57 | 23 | name: linux |
58 | | - - os: macos-latest |
59 | | - name: macos |
60 | 24 | - os: windows-latest |
61 | 25 | name: windows |
62 | | - runs-on: ${{ matrix.os }} |
| 26 | + - os: macos-latest |
| 27 | + name: macos |
| 28 | + |
63 | 29 | steps: |
64 | 30 | - uses: actions/checkout@v4 |
65 | 31 |
|
66 | | - - name: Extract Metadata & Validate |
67 | | - id: meta |
68 | | - shell: bash |
69 | | - run: | |
70 | | - PYPROJECT_VERSION=$(python - <<EOF |
71 | | - import tomllib, pathlib |
72 | | - data = tomllib.loads(pathlib.Path("pyproject.toml").read_text()) |
73 | | - print(data["project"]["version"]) |
74 | | - EOF |
75 | | - ) |
76 | | -
|
77 | | - if [[ "${GITHUB_REF}" == refs/tags/* ]]; then |
78 | | - VERSION=${GITHUB_REF_NAME#v} |
79 | | - else |
80 | | - VERSION=$PYPROJECT_VERSION |
81 | | - fi |
82 | | -
|
83 | | - SHA=$(git rev-parse --short HEAD) |
84 | | - DEPS_HASH=$(python - <<EOF |
85 | | - import hashlib, pathlib |
86 | | - p = pathlib.Path("pyproject.toml") |
87 | | - print(hashlib.sha256(p.read_bytes()).hexdigest()[:16]) |
88 | | - EOF |
89 | | - ) |
90 | | -
|
91 | | - echo "VERSION=$VERSION" >> $GITHUB_OUTPUT |
92 | | - echo "SHA=$SHA" >> $GITHUB_OUTPUT |
93 | | - echo "CACHE_KEY=${{ runner.os }}-$VERSION-$DEPS_HASH" >> $GITHUB_OUTPUT |
94 | | -
|
95 | | - - name: Setup Python |
96 | | - uses: actions/setup-python@v5 |
| 32 | + - uses: actions/setup-python@v5 |
97 | 33 | with: |
98 | 34 | python-version: "3.11" |
99 | | - cache: "pip" |
100 | 35 |
|
101 | | - - name: Cache Nuitka |
| 36 | + - name: Cache pip |
102 | 37 | uses: actions/cache@v4 |
103 | 38 | with: |
104 | 39 | path: | |
105 | 40 | ~/.cache/pip |
106 | | - ~/.cache/Nuitka |
107 | | - ~/Library/Caches/Nuitka |
108 | | - ~\AppData\Local\Nuitka\Nuitka\Cache |
109 | | - key: nuitka-${{ steps.meta.outputs.CACHE_KEY }} |
110 | | - restore-keys: | |
111 | | - nuitka-${{ runner.os }}- |
112 | | -
|
113 | | - - name: Install System Dependencies (Linux) |
114 | | - if: runner.os == 'Linux' |
115 | | - run: sudo apt-get update && sudo apt-get install -y build-essential patchelf |
| 41 | + ~/AppData/Local/pip/Cache |
| 42 | + key: pip-${{ runner.os }}-${{ hashFiles('requirements*.txt') }} |
| 43 | + restore-keys: pip-${{ runner.os }}- |
116 | 44 |
|
117 | | - - name: Install System Dependencies (macOS) |
118 | | - if: runner.os == 'macOS' |
119 | | - run: xcode-select -p || xcode-select --install || true |
| 45 | + - name: Install system deps (Linux) |
| 46 | + if: runner.os == 'Linux' |
| 47 | + run: sudo apt-get update && sudo apt-get install -y patchelf |
120 | 48 |
|
121 | | - - name: MSVC Setup (Windows) |
| 49 | + - name: MSVC setup (Windows) |
122 | 50 | if: runner.os == 'Windows' |
123 | 51 | uses: ilammy/msvc-dev-cmd@v1 |
124 | 52 |
|
125 | | - - name: Install Python Dependencies |
| 53 | + - name: Install Python deps |
| 54 | + shell: bash |
126 | 55 | run: | |
127 | | - python -m pip install -U pip wheel |
128 | | - pip install "setuptools<72" |
129 | | - pip install nuitka[onefile] |
130 | | - pip install . |
| 56 | + python -m pip install -U pip wheel nuitka |
| 57 | + [[ -f requirements.txt ]] && pip install -r requirements.txt || true |
131 | 58 |
|
132 | | - - name: Create Entrypoint Script |
| 59 | + - name: Write entrypoint |
133 | 60 | shell: bash |
134 | 61 | run: | |
135 | | - cat > _entry.py << 'EOF' |
136 | | - from bangen.app import main |
137 | | - if __name__ == "__main__": |
138 | | - main() |
139 | | - EOF |
| 62 | + printf 'from bangen.app import main\nif __name__ == "__main__":\n main()\n' > _entry.py |
140 | 63 |
|
141 | 64 | - name: Build with Nuitka |
142 | 65 | shell: bash |
143 | 66 | run: | |
| 67 | + JOBS=$(nproc 2>/dev/null || sysctl -n hw.ncpu 2>/dev/null || echo 2) |
144 | 68 | python -m nuitka \ |
145 | 69 | --onefile \ |
146 | | - --jobs=auto \ |
| 70 | + --lto=thin \ |
| 71 | + --jobs="$JOBS" \ |
147 | 72 | --assume-yes-for-downloads \ |
148 | 73 | --output-dir=build \ |
149 | 74 | --output-filename=bangen \ |
150 | | - --nofollow-import-to=tkinter \ |
151 | | - --nofollow-import-to=unittest \ |
152 | | - --nofollow-import-to=test \ |
153 | | - --python-flag=no_asserts \ |
154 | | - --python-flag=no_docstrings \ |
155 | | - --python-flag=isolated \ |
156 | | - --onefile-tempdir-spec="{TEMP}/bangen" \ |
157 | | - --plugin-enable=anti-bloat \ |
| 75 | + --follow-imports \ |
| 76 | + --nofollow-import-to=tkinter,unittest,test,distutils,setuptools,pkg_resources \ |
| 77 | + --python-flag=no_asserts,no_docstrings,isolated \ |
| 78 | + --onefile-tempdir-spec="{CACHE_DIR}/bangen/${{ github.ref_name }}" \ |
158 | 79 | _entry.py |
159 | 80 |
|
160 | | - - name: Stage Artifact |
| 81 | + - name: Package artifact |
161 | 82 | shell: bash |
162 | 83 | run: | |
163 | 84 | mkdir -p dist |
164 | | - NAME="bangen-${{ matrix.name }}-${{ steps.meta.outputs.VERSION }}-${{ steps.meta.outputs.SHA }}" |
| 85 | + NAME="bangen-${{ matrix.name }}-${{ github.ref_name }}" |
165 | 86 | if [[ "$RUNNER_OS" == "Windows" ]]; then |
166 | | - mv build/bangen.exe "dist/$NAME.exe" |
| 87 | + mv build/bangen.exe dist/"$NAME.exe" |
| 88 | + (cd dist && zip "$NAME.zip" "$NAME.exe" && rm "$NAME.exe") |
167 | 89 | else |
168 | | - mv build/bangen "dist/$NAME" |
| 90 | + mv build/bangen dist/"$NAME" |
| 91 | + (cd dist && tar -czf "$NAME.tar.gz" "$NAME" && rm "$NAME") |
169 | 92 | fi |
170 | 93 |
|
171 | | - - name: Upload Artifact |
172 | | - uses: actions/upload-artifact@v4 |
| 94 | + - uses: actions/upload-artifact@v4 |
173 | 95 | with: |
174 | 96 | name: ${{ matrix.name }}-build |
175 | 97 | path: dist/* |
176 | 98 |
|
177 | | - # --- Release Job --- |
178 | | - # Consolidates all builds and creates a draft GitHub Release |
179 | 99 | release: |
180 | | - needs: [tag, build] |
| 100 | + name: Publish Release |
| 101 | + needs: build |
181 | 102 | runs-on: ubuntu-latest |
| 103 | + permissions: |
| 104 | + contents: write # required for action-gh-release to create releases |
| 105 | + |
182 | 106 | steps: |
183 | 107 | - uses: actions/download-artifact@v4 |
184 | 108 | with: |
185 | 109 | path: artifacts |
186 | 110 | merge-multiple: true |
187 | 111 |
|
188 | | - - name: Create Draft Release |
189 | | - uses: softprops/action-gh-release@v2 |
| 112 | + - uses: softprops/action-gh-release@v2 |
190 | 113 | with: |
191 | | - tag_name: v${{ needs.tag.outputs.version }} |
192 | | - name: Bangen v${{ needs.tag.outputs.version }} |
193 | | - draft: true |
| 114 | + tag_name: ${{ github.ref_name }} |
| 115 | + name: Bangen ${{ github.ref_name }} |
194 | 116 | files: artifacts/* |
0 commit comments