XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet
公开
关注 0 Fork 0 Star 1
UTF-8
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 Executable
  build-windows-exe:
    runs-on: windows-latest
    needs: prepare
    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 pyinstaller
          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
        env:
          G4F_VERSION: ${{ needs.prepare.outputs.version }}
        run: |
          pyinstaller --onefile --name g4f-windows-${{ needs.prepare.outputs.version }} --icon projects/windows/icon.ico g4f_cli.py
      - name: Upload Windows executable
        uses: actions/upload-artifact@v4
        with:
          name: windows-exe
          path: dist/g4f-windows-*.exe

  # Linux Executable
  build-linux-exe:
    runs-on: ubuntu-latest
    needs: prepare
    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-slim.txt
          pip install pyinstaller
          pip install -e .
      - name: Build Linux executable
        env:
          G4F_VERSION: ${{ needs.prepare.outputs.version }}
        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
          pyinstaller --onefile --name g4f-linux-${{ needs.prepare.outputs.version }} g4f_cli.py
      - name: Make executable
        run: chmod +x dist/g4f-linux-*
      - name: Upload Linux executable
        uses: actions/upload-artifact@v4
        with:
          name: linux-exe
          path: dist/g4f-linux-*

  # macOS Executable
  build-macos-exe:
    runs-on: macos-latest
    needs: prepare
    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 pyinstaller
          pip install -e .
      - name: Build macOS executable
        env:
          G4F_VERSION: ${{ needs.prepare.outputs.version }}
        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
          pyinstaller --onefile --name g4f-macos-${{ needs.prepare.outputs.version }} g4f_cli.py
      - name: Upload macOS executable
        uses: actions/upload-artifact@v4
        with:
          name: macos-exe
          path: dist/g4f-macos-*

  # Docker Images (reuse existing workflow logic)
  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
          python -m pip install --upgrade pip
          pip install -r requirements-min.txt
          pip 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
        uses: actions/download-artifact@v4
        with:
          name: windows-exe
          path: ./artifacts
      - name: Calculate hash
        id: hash
        run: |
          HASH=$(sha256sum ./artifacts/g4f-windows-*.exe | cut -d' ' -f1)
          echo "hash=${HASH}" >> $GITHUB_OUTPUT
          SIZE=$(stat -c%s ./artifacts/g4f-windows-*.exe)
          echo "size=${SIZE}" >> $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: exe
            InstallerUrl: https://github.com/xtekky/gpt4free/releases/download/${{ needs.prepare.outputs.version }}/g4f-windows-${{ needs.prepare.outputs.version }}.exe
            InstallerSha256: ${{ steps.hash.outputs.hash }}
            InstallerSwitches:
              Silent: /S
              SilentWithProgress: /S
          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, build-debian, 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 }}
          body: |
            ## g4f ${{ needs.prepare.outputs.version }}
            
            ### Download Options
            
            **Python Package:**
            - PyPI: `pip install g4f==${{ needs.prepare.outputs.version }}`
            
            **Executables:**
            - Windows: Download `g4f-windows-${{ needs.prepare.outputs.version }}.exe`
            - Linux: Download `g4f-linux-${{ needs.prepare.outputs.version }}`  
            - macOS: Download `g4f-macos-${{ needs.prepare.outputs.version }}`
            
            **Debian Packages:**
            - AMD64: `g4f-${{ needs.prepare.outputs.version }}-amd64.deb`
            - ARM64: `g4f-${{ needs.prepare.outputs.version }}-arm64.deb`
            - ARMv7: `g4f-${{ needs.prepare.outputs.version }}-armhf.deb`
            
            **System Packages:**
            - WinGet: `winget install g4f` (after manifest approval)
            
            **Docker:**
            - `docker pull hlohaus789/g4f:${{ needs.prepare.outputs.version }}`
            - `docker pull hlohaus789/g4f:${{ needs.prepare.outputs.version }}-slim`
          draft: false
          prerelease: false
          files: |
            ./artifacts/pypi-package/*
            ./artifacts/windows-exe/*
            ./artifacts/linux-exe/*
            ./artifacts/macos-exe/*
            ./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