name: build-release on: push: tags: - 'v*' workflow_dispatch: inputs: tag: description: 'Release tag to create (e.g. v0.1.0)' required: true type: string prerelease: description: 'Mark release as prerelease' required: false type: boolean default: false permissions: contents: write jobs: build: name: build (${{ matrix.asset_name }}) runs-on: ${{ matrix.os }} container: ${{ matrix.container }} strategy: fail-fast: false matrix: include: - os: ubuntu-latest container: quay.io/pypa/manylinux_2_28_x86_64 asset_name: xpoz-cli-linux-amd64 strip_flag: "--strip" - os: ubuntu-24.04-arm container: quay.io/pypa/manylinux_2_28_aarch64 asset_name: xpoz-cli-linux-arm64 strip_flag: "--strip" - os: macos-14 asset_name: xpoz-cli-macos-arm64 strip_flag: "--strip" - os: windows-latest asset_name: xpoz-cli-windows-amd64.exe strip_flag: "" steps: - uses: actions/checkout@v4 with: fetch-depth: 0 # setuptools-scm needs full history + tags # manylinux's /opt/python/cpXY is built WITHOUT --enable-shared # (it ships a static CPython for wheel-building), so PyInstaller # can't find libpython.so. Use uv to install a # python-build-standalone distribution which DOES ship # libpython.so, and activate a venv from it. - name: Install uv + shared CPython (manylinux) if: ${{ matrix.container }} shell: bash run: | set -euo pipefail curl -LsSf https://astral.sh/uv/install.sh | sh export PATH="$HOME/.local/bin:$PATH" echo "$HOME/.local/bin" >> "$GITHUB_PATH" uv python install 3.14 uv venv --seed --python 3.14 "$HOME/build-venv" echo "$HOME/build-venv/bin" >> "$GITHUB_PATH" echo "VIRTUAL_ENV=$HOME/build-venv" >> "$GITHUB_ENV" - uses: actions/setup-python@v5 if: ${{ !matrix.container }} with: python-version: '3.14' - name: Install dependencies shell: bash run: | python -m pip install --upgrade pip pip install pyinstaller xpoz - name: Write _xpoz_cli_version.py from tag shell: bash run: | set -euo pipefail if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then tag="${{ inputs.tag }}" else tag="${{ github.ref_name }}" fi version="${tag#v}" printf '__version__ = "%s"\n' "$version" > _xpoz_cli_version.py cat _xpoz_cli_version.py - name: Build with PyInstaller shell: bash run: pyinstaller --onefile --name xpoz-cli --clean ${{ matrix.strip_flag }} xpoz_cli.py - name: Rename artifact shell: bash run: | src="dist/xpoz-cli" [[ "${{ runner.os }}" == "Windows" ]] && src="dist/xpoz-cli.exe" mv "$src" "dist/${{ matrix.asset_name }}" - name: Smoke test shell: bash run: | chmod +x "dist/${{ matrix.asset_name }}" || true "./dist/${{ matrix.asset_name }}" --help > /dev/null - name: Report binary size shell: bash run: ls -lh "dist/${{ matrix.asset_name }}" - uses: actions/upload-artifact@v4 with: name: ${{ matrix.asset_name }} path: dist/${{ matrix.asset_name }} if-no-files-found: error retention-days: 7 release: name: publish release needs: build runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/download-artifact@v4 with: path: dist merge-multiple: true - name: List artifacts run: ls -lh dist - name: Generate SHA256SUMS shell: bash working-directory: dist run: | sha256sum xpoz-cli-* > SHA256SUMS echo "--- SHA256SUMS ---" cat SHA256SUMS - name: Resolve tag and flags id: meta shell: bash run: | if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then echo "tag=${{ inputs.tag }}" >> "$GITHUB_OUTPUT" if [[ "${{ inputs.prerelease }}" == "true" ]]; then echo "prerelease_flag=--prerelease" >> "$GITHUB_OUTPUT" else echo "prerelease_flag=" >> "$GITHUB_OUTPUT" fi else echo "tag=${{ github.ref_name }}" >> "$GITHUB_OUTPUT" echo "prerelease_flag=" >> "$GITHUB_OUTPUT" fi - name: Create GitHub Release env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | gh release create "${{ steps.meta.outputs.tag }}" \ --title "${{ steps.meta.outputs.tag }}" \ --generate-notes \ ${{ steps.meta.outputs.prerelease_flag }} \ dist/xpoz-cli-* dist/SHA256SUMS