name: Build All Packages on: push: tags: - '*' workflow_dispatch: inputs: version: description: 'Version to build (leave empty for auto)' required: false type: string jobs: prepare: runs-on: ubuntu-latest outputs: version: ${{ steps.version.outputs.version }} is_release: ${{ steps.version.outputs.is_release }} steps: - uses: actions/checkout@v4 - name: Determine version id: version run: | if [[ "${{ github.ref }}" =~ ^refs/tags/ ]]; then G4F_VERSION="${{ github.ref_name }}" IS_RELEASE="true" elif [[ -n "${{ inputs.version }}" ]]; then G4F_VERSION="${{ inputs.version }}" IS_RELEASE="false" else G4F_VERSION="0.0.0-dev" IS_RELEASE="false" fi echo "version=${G4F_VERSION}" >> $GITHUB_OUTPUT echo "is_release=${IS_RELEASE}" >> $GITHUB_OUTPUT echo "Building version: ${G4F_VERSION}" # PyPI Package build-pypi: runs-on: ubuntu-latest needs: prepare steps: - uses: actions/checkout@v4 - name: Set up Python uses: actions/setup-python@v5 with: python-version: "3.x" - name: Install build tools run: | python -m pip install --upgrade pip python -m pip install build twine - name: Build package env: G4F_VERSION: ${{ needs.prepare.outputs.version }} run: python -m build - name: Verify package run: | python -m twine check dist/* ls -la dist/ - name: Upload PyPI artifacts uses: actions/upload-artifact@v4 with: name: pypi-package path: dist/ # Windows Executables build-windows-exe: runs-on: windows-latest needs: prepare strategy: matrix: include: - architecture: x64 runner-arch: x86_64 # Note: ARM64 cross-compilation on Windows requires additional setup # Keeping architecture in matrix for future expansion steps: - uses: actions/checkout@v4 - name: Set up Python uses: actions/setup-python@v5 with: python-version: "3.11" - name: Install dependencies run: | python -m pip install --upgrade pip pip install -r requirements.txt pip install nuitka pip install -e . - name: Write g4f_cli.py shell: pwsh run: | @" #!/usr/bin/env python3 """ Entry point for g4f CLI executable builds """ import g4f.debug g4f.debug.version_check = False g4f.debug.version = "${{ needs.prepare.outputs.version }}" if __name__ == "__main__": from g4f.cli import main main() "@ | Set-Content -Path g4f_cli.py -Encoding utf8 - name: Build Windows executable with Nuitka env: G4F_VERSION: ${{ needs.prepare.outputs.version }} PLATFORM: windows ARCHITECTURE: ${{ matrix.runner-arch }} shell: bash run: | chmod +x scripts/build-nuitka.sh ./scripts/build-nuitka.sh - name: Zip Windows executable folder shell: pwsh run: | $architecture = "${{ matrix.architecture }}" $version = "${{ needs.prepare.outputs.version }}" $exeName = "g4f-windows-${version}-${architecture}.exe" if (Test-Path "dist\${exeName}") { Compress-Archive "dist\${exeName}" "dist\g4f-windows-${version}-${architecture}.zip" } - name: Upload Windows zip archive uses: actions/upload-artifact@v4 with: name: windows-exe-${{ matrix.architecture }} path: dist/g4f-windows-*.zip # Linux Executables build-linux-exe: runs-on: ${{ matrix.runner }} needs: prepare strategy: matrix: include: - architecture: x64 runner: ubuntu-latest runner-arch: x86_64 - architecture: arm64 runner: ubuntu-24.04-arm runner-arch: aarch64 steps: - uses: actions/checkout@v4 - name: Set up Python uses: actions/setup-python@v5 with: python-version: "3.11" - name: Install dependencies run: | python -m pip install --upgrade pip pip install -r requirements.txt pip install nuitka pip install -e . - name: Write g4f_cli.py run: | cat > g4f_cli.py << EOF #!/usr/bin/env python3 """ Entry point for g4f CLI executable builds """ import g4f.debug g4f.debug.version_check = False g4f.debug.version = "${{ needs.prepare.outputs.version }}" if __name__ == "__main__": from g4f.cli import main main() EOF - name: Build Linux executable with Nuitka env: G4F_VERSION: ${{ needs.prepare.outputs.version }} PLATFORM: linux ARCHITECTURE: ${{ matrix.runner-arch }} run: | chmod +x scripts/build-nuitka.sh ./scripts/build-nuitka.sh - name: Upload Linux executable uses: actions/upload-artifact@v4 with: name: linux-exe-${{ matrix.architecture }} path: dist/g4f-linux-* # macOS Executables build-macos-exe: runs-on: macos-latest needs: prepare strategy: matrix: include: - architecture: x64 runner-arch: x86_64 - architecture: arm64 runner-arch: arm64 steps: - uses: actions/checkout@v4 - name: Set up Python uses: actions/setup-python@v5 with: python-version: "3.11" - name: Install dependencies run: | python -m pip install --upgrade pip pip install -r requirements.txt pip install nuitka pip install -e . - name: Write g4f_cli.py run: | cat > g4f_cli.py << EOF #!/usr/bin/env python3 """ Entry point for g4f CLI executable builds """ import g4f.debug g4f.debug.version_check = False g4f.debug.version = "${{ needs.prepare.outputs.version }}" if __name__ == "__main__": from g4f.cli import main main() EOF - name: Build macOS executable with Nuitka env: G4F_VERSION: ${{ needs.prepare.outputs.version }} PLATFORM: darwin ARCHITECTURE: ${{ matrix.runner-arch }} run: | chmod +x scripts/build-nuitka.sh ./scripts/build-nuitka.sh - name: Upload macOS executable uses: actions/upload-artifact@v4 with: name: macos-exe-${{ matrix.architecture }} path: dist/g4f-macos-* # Docker Images build-docker: runs-on: ubuntu-latest needs: prepare if: needs.prepare.outputs.is_release == 'true' steps: - name: Checkout repository uses: actions/checkout@v4 - name: Set up QEMU uses: docker/setup-qemu-action@v3 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - name: Get metadata for Docker id: metadata uses: docker/metadata-action@v5 with: images: | hlohaus789/g4f - name: Log in to Docker Hub uses: docker/login-action@f4ef78c080cd8ba55a85445d5b36e214a81df20a with: username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_PASSWORD }} - name: Build and push armv7 image uses: docker/build-push-action@v5 with: context: . file: docker/Dockerfile-armv7 platforms: linux/arm/v7 push: true tags: | hlohaus789/g4f:latest-armv7 hlohaus789/g4f:${{ needs.prepare.outputs.version }}-armv7 labels: ${{ steps.metadata.outputs.labels }} build-args: | G4F_VERSION=${{ needs.prepare.outputs.version }} - name: Build and push slim images uses: docker/build-push-action@v5 with: context: . file: docker/Dockerfile-slim platforms: linux/amd64,linux/arm64 push: true tags: | hlohaus789/g4f:latest-slim hlohaus789/g4f:${{ needs.prepare.outputs.version }}-slim labels: ${{ steps.metadata.outputs.labels }} build-args: | G4F_VERSION=${{ needs.prepare.outputs.version }} - name: Build and push image uses: docker/build-push-action@v5 with: context: . file: docker/Dockerfile platforms: linux/amd64 push: true tags: ${{ steps.metadata.outputs.tags }} labels: ${{ steps.metadata.outputs.labels }} build-args: | G4F_VERSION=${{ needs.prepare.outputs.version }} # Debian Packages # build-debian: # runs-on: ubuntu-latest # needs: prepare # strategy: # matrix: # architecture: [amd64, arm64, armhf] # steps: # - uses: actions/checkout@v4 # - name: Set up Python # uses: actions/setup-python@v5 # with: # python-version: "3.x" # - name: Install build dependencies # run: | # sudo apt-get update # sudo apt-get install -y dpkg-dev build-essential python3-setuptools # python3 -m pip install --upgrade pip # pip3 install -r requirements-min.txt # pip3 install -e . # - name: Build Debian package # env: # G4F_VERSION: ${{ needs.prepare.outputs.version }} # ARCH: ${{ matrix.architecture }} # run: | # chmod +x scripts/build-deb.sh # ./scripts/build-deb.sh # - name: Upload Debian package # uses: actions/upload-artifact@v4 # with: # name: debian-${{ matrix.architecture }} # path: g4f-*-${{ matrix.architecture }}.deb # WinGet Package Manifest create-winget-manifest: runs-on: ubuntu-latest needs: [prepare, build-windows-exe] if: needs.prepare.outputs.is_release == 'true' steps: - uses: actions/checkout@v4 - name: Download Windows executable zip (x64) uses: actions/download-artifact@v4 with: name: windows-exe-x64 path: ./artifacts/x64 - name: Calculate hash and size of ZIP id: hash run: | HASH_X64=$(sha256sum ./artifacts/x64/g4f-windows-*-x64.zip | cut -d' ' -f1) echo "hash_x64=${HASH_X64}" >> $GITHUB_OUTPUT SIZE_X64=$(stat -c%s ./artifacts/x64/g4f-windows-*-x64.zip) echo "size_x64=${SIZE_X64}" >> $GITHUB_OUTPUT - name: Create WinGet manifest run: | mkdir -p winget/manifests/g/g4f/${{ needs.prepare.outputs.version }} # Version manifest cat > winget/manifests/g/g4f/${{ needs.prepare.outputs.version }}/g4f.yaml << EOF PackageIdentifier: g4f PackageVersion: ${{ needs.prepare.outputs.version }} DefaultLocale: en-US ManifestType: version ManifestVersion: 1.4.0 EOF # Installer manifest cat > winget/manifests/g/g4f/${{ needs.prepare.outputs.version }}/g4f.installer.yaml << EOF PackageIdentifier: g4f PackageVersion: ${{ needs.prepare.outputs.version }} Installers: - Architecture: x64 InstallerType: zip NestedInstallerType: portable NestedInstallerFiles: - RelativeFilePath: g4f-windows-${{ needs.prepare.outputs.version }}-x64.exe PortableCommandAlias: g4f InstallerUrl: https://github.com/xtekky/gpt4free/releases/download/${{ needs.prepare.outputs.version }}/g4f-windows-${{ needs.prepare.outputs.version }}-x64.zip InstallerSha256: ${{ steps.hash.outputs.hash_x64 }} ManifestType: installer ManifestVersion: 1.4.0 EOF # Locale manifest cat > winget/manifests/g/g4f/${{ needs.prepare.outputs.version }}/g4f.locale.en-US.yaml << EOF PackageIdentifier: g4f PackageVersion: ${{ needs.prepare.outputs.version }} PackageLocale: en-US Publisher: GPT4Free PublisherUrl: https://github.com/xtekky/gpt4free PackageName: g4f PackageUrl: https://github.com/xtekky/gpt4free License: GPL-3.0 LicenseUrl: https://github.com/xtekky/gpt4free/blob/main/LICENSE ShortDescription: The official gpt4free repository Description: Various collection of powerful language models Tags: - ai - gpt - chatgpt - openai - free - client ManifestType: defaultLocale ManifestVersion: 1.4.0 EOF - name: Upload WinGet manifest uses: actions/upload-artifact@v4 with: name: winget-manifest path: winget/ # Release Creation create-release: runs-on: ubuntu-latest needs: [prepare, build-pypi, build-windows-exe, build-linux-exe, build-macos-exe, create-winget-manifest] if: needs.prepare.outputs.is_release == 'true' permissions: contents: write steps: - uses: actions/checkout@v4 - name: Download all artifacts uses: actions/download-artifact@v4 with: path: ./artifacts - name: Display artifact structure run: | echo "Downloaded artifacts:" find ./artifacts -type f -name "*" | sort - name: Create Release with Assets uses: softprops/action-gh-release@v2 with: tag_name: ${{ needs.prepare.outputs.version }} name: Release ${{ needs.prepare.outputs.version }} append_body: true body: | ## g4f ${{ needs.prepare.outputs.version }} ### Download Options **Python Package:** - PyPI: `pip install g4f==${{ needs.prepare.outputs.version }}` **Executables:** - Windows x64: `g4f-windows-${{ needs.prepare.outputs.version }}-x64.zip` - Linux x64: `g4f-linux-${{ needs.prepare.outputs.version }}-x64` - Linux ARM64: `g4f-linux-${{ needs.prepare.outputs.version }}-arm64` - macOS x64: `g4f-macos-${{ needs.prepare.outputs.version }}-x64` - macOS ARM64: `g4f-macos-${{ needs.prepare.outputs.version }}-arm64` **System Packages:** - WinGet: `winget install gpt4free` **Docker:** - `docker pull hlohaus789/g4f:${{ needs.prepare.outputs.version }}` - `docker pull hlohaus789/g4f:${{ needs.prepare.outputs.version }}-slim` 💻 **Having trouble with the .exe from this release?** 👉 Check out the Windows launcher for GPT4Free instead: 🔗 [https://github.com/gpt4free/g4f.exe](https://github.com/gpt4free/g4f.exe) 🚀 draft: false prerelease: false files: | ./artifacts/pypi-package/* ./artifacts/windows-exe-x64/* ./artifacts/linux-exe-x64/* ./artifacts/linux-exe-arm64/* ./artifacts/macos-exe-x64/* ./artifacts/macos-exe-arm64/* ./artifacts/debian-amd64/* ./artifacts/debian-arm64/* ./artifacts/debian-armhf/* token: ${{ secrets.GITHUB_TOKEN }} # Publish to PyPI (only for releases) # publish-pypi: # runs-on: ubuntu-latest # needs: [prepare, build-pypi, create-release] # if: needs.prepare.outputs.is_release == 'true' # environment: # name: pypi # url: https://pypi.org/p/g4f # permissions: # id-token: write # steps: # - name: Download PyPI artifacts # uses: actions/download-artifact@v4 # with: # name: pypi-package # path: dist/ # - name: Publish to PyPI # uses: pypa/gh-action-pypi-publish@release/v1