context7-cli 0.4.2

Search library documentation from your terminal — zero runtime, bilingual (EN/PT), multi-key rotation
Documentation
name: Release

on:
  push:
    tags:
      - 'v*'
  workflow_dispatch:
    inputs:
      dry_run:
        description: 'Dry run (não publica de verdade)'
        required: false
        default: 'true'
        type: boolean

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: false

permissions:
  contents: read

env:
  CARGO_TERM_COLOR: always
  CARGO_INCREMENTAL: 0

jobs:
  validate:
    name: Validar antes de publicar
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Instalar toolchain Rust estável
        uses: dtolnay/rust-toolchain@stable
        with:
          components: rustfmt, clippy

      - name: Cache de dependências Rust
        uses: Swatinem/rust-cache@v2
        with:
          shared-key: ubuntu-stable-release

      - name: Verificar formatação
        run: cargo fmt --all --check

      - name: Clippy sem warnings
        run: cargo clippy --all-targets --all-features -- -D warnings

      - name: Testes completos
        run: cargo test --all-features

      - name: Documentação sem warnings
        run: cargo doc --no-deps --all-features
        env:
          RUSTDOCFLAGS: -D warnings

      - name: Dry-run de publicação
        run: cargo publish --dry-run

  build-matrix:
    name: Build release (${{ matrix.target }})
    needs: validate
    runs-on: ${{ matrix.os }}
    strategy:
      fail-fast: false
      matrix:
        include:
          - os: ubuntu-latest
            target: x86_64-unknown-linux-gnu
            binary_name: context7
            archive_ext: tar.gz
          - os: ubuntu-latest
            target: x86_64-unknown-linux-musl
            binary_name: context7
            archive_ext: tar.gz
          - os: macos-latest
            target: aarch64-apple-darwin
            binary_name: context7
            archive_ext: tar.gz
          - os: macos-latest
            target: x86_64-apple-darwin
            binary_name: context7
            archive_ext: tar.gz
          - os: windows-latest
            target: x86_64-pc-windows-msvc
            binary_name: context7.exe
            archive_ext: zip
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Instalar toolchain Rust estável
        uses: dtolnay/rust-toolchain@stable
        with:
          targets: ${{ matrix.target }}

      - name: Instalar musl-tools (Linux musl)
        if: matrix.target == 'x86_64-unknown-linux-musl'
        run: sudo apt-get update && sudo apt-get install -y musl-tools

      - name: Cache de dependências Rust
        uses: Swatinem/rust-cache@v2
        with:
          shared-key: ${{ matrix.os }}-${{ matrix.target }}-release

      - name: Build release
        run: cargo build --release --target ${{ matrix.target }}

      - name: Empacotar artefato (Linux/macOS)
        if: matrix.archive_ext == 'tar.gz'
        shell: bash
        run: |
          ARCHIVE="context7-${{ matrix.target }}.tar.gz"
          tar -czf "$ARCHIVE" -C "target/${{ matrix.target }}/release" "${{ matrix.binary_name }}"
          echo "ARCHIVE=$ARCHIVE" >> "$GITHUB_ENV"

      - name: Empacotar artefato (Windows)
        if: matrix.archive_ext == 'zip'
        shell: pwsh
        run: |
          $archive = "context7-${{ matrix.target }}.zip"
          Compress-Archive -Path "target/${{ matrix.target }}/release/${{ matrix.binary_name }}" -DestinationPath $archive
          "ARCHIVE=$archive" | Out-File -FilePath $env:GITHUB_ENV -Append

      - name: Upload artefato de build
        uses: actions/upload-artifact@v7
        with:
          name: context7-${{ matrix.target }}
          path: context7-${{ matrix.target }}.${{ matrix.archive_ext }}
          retention-days: 7
          if-no-files-found: error

  macos-universal:
    name: Universal Binary macOS (lipo)
    needs: build-matrix
    runs-on: macos-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Baixar artefato aarch64-apple-darwin
        uses: actions/download-artifact@v8
        with:
          name: context7-aarch64-apple-darwin
          path: artifacts/aarch64

      - name: Baixar artefato x86_64-apple-darwin
        uses: actions/download-artifact@v8
        with:
          name: context7-x86_64-apple-darwin
          path: artifacts/x86_64

      - name: Extrair binários
        run: |
          tar -xzf artifacts/aarch64/context7-aarch64-apple-darwin.tar.gz -C artifacts/aarch64
          tar -xzf artifacts/x86_64/context7-x86_64-apple-darwin.tar.gz -C artifacts/x86_64

      - name: Criar Universal Binary com lipo
        run: |
          lipo -create \
            artifacts/aarch64/context7 \
            artifacts/x86_64/context7 \
            -output context7-universal
          # Verificar que o universal binary contém ambas as arquiteturas
          lipo -info context7-universal

      - name: Assinar Universal Binary (adhoc ou Developer ID)
        env:
          APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
          APPLE_ID: ${{ secrets.APPLE_ID }}
          APPLE_APP_PASSWORD: ${{ secrets.APPLE_APP_PASSWORD }}
        run: |
          if [ -z "${APPLE_TEAM_ID:-}" ]; then
            # Caminho sem certificado Apple Developer: assinatura adhoc
            codesign --sign - --force context7-universal
            echo "Assinatura adhoc aplicada (sem certificado Apple Developer)"
          else
            # Caminho com certificado Developer ID Application
            codesign --sign "Developer ID Application: $APPLE_TEAM_ID" \
              --options runtime \
              --force \
              context7-universal
            # Empacotar para submissão de notarização
            zip context7-universal-notarize.zip context7-universal
            # Submeter para o serviço de notarização da Apple
            xcrun notarytool submit context7-universal-notarize.zip \
              --apple-id "$APPLE_ID" \
              --password "$APPLE_APP_PASSWORD" \
              --team-id "$APPLE_TEAM_ID" \
              --wait
            # Staple do ticket de notarização no binário
            xcrun stapler staple context7-universal || true
          fi

      - name: Smoke test Universal Binary
        run: |
          chmod +x context7-universal
          ./context7-universal --version
          ./context7-universal --help

      - name: Empacotar Universal Binary
        run: |
          tar -czf context7-macos-universal.tar.gz context7-universal

      - name: Upload Universal Binary
        uses: actions/upload-artifact@v7
        with:
          name: context7-macos-universal
          path: context7-macos-universal.tar.gz
          retention-days: 7
          if-no-files-found: error

  build-flatpak:
    name: Build Flatpak
    needs: validate
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Instalar dependências do Flatpak e flatpak-builder
        run: |
          sudo apt-get update
          sudo apt-get install -y flatpak flatpak-builder

      - name: Adicionar remote Flathub (para SDK)
        run: |
          sudo flatpak remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo
          sudo flatpak install -y flathub org.freedesktop.Platform//24.08 org.freedesktop.Sdk//24.08 org.freedesktop.Sdk.Extension.rust-stable//24.08

      - name: Build Flatpak bundle
        run: |
          flatpak-builder \
            --repo=flatpak-repo \
            --force-clean \
            flatpak-build \
            packaging/flatpak/br.com.daniloaguiar.context7-cli.yaml
          flatpak build-bundle \
            flatpak-repo \
            context7-cli.flatpak \
            br.com.daniloaguiar.context7-cli

      - name: Upload artefato Flatpak
        uses: actions/upload-artifact@v7
        with:
          name: context7-flatpak
          path: context7-cli.flatpak
          retention-days: 7
          if-no-files-found: error

  build-snap:
    name: Build Snap
    needs: validate
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Copiar snapcraft.yaml para raiz do repositório
        run: cp packaging/snap/snapcraft.yaml .

      - name: Build Snap package
        uses: snapcore/action-build@v1
        id: build-snap
        with:
          snapcraft-args: --destructive-mode

      - name: Upload artefato Snap
        uses: actions/upload-artifact@v7
        with:
          name: context7-snap
          path: ${{ steps.build-snap.outputs.snap }}
          retention-days: 7
          if-no-files-found: error

  publish-github-release:
    name: Publicar GitHub Release
    needs: [validate, build-matrix, macos-universal, build-flatpak, build-snap]
    runs-on: ubuntu-latest
    if: |
      always() &&
      (github.event_name == 'push' || (github.event_name == 'workflow_dispatch' && github.event.inputs.dry_run == 'false')) &&
      needs.validate.result == 'success' &&
      needs.build-matrix.result == 'success' &&
      needs.macos-universal.result == 'success'
    permissions:
      contents: write
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Instalar ripgrep
        run: sudo apt-get update && sudo apt-get install -y ripgrep

      - name: Baixar todos os artefatos de build
        uses: actions/download-artifact@v8
        with:
          path: artifacts

      - name: Listar artefatos baixados
        shell: bash
        run: |
          shopt -s globstar nullglob
          printf '%s\n' artifacts/**/* | sort

      - name: Extrair versão do Cargo.toml
        shell: bash
        run: |
          VERSION=$(rg -m1 -o '^version\s*=\s*"(.+)"' Cargo.toml -r '$1')
          echo "VERSION=$VERSION" >> "$GITHUB_ENV"
          echo "Versão detectada: $VERSION"

      - name: Publicar GitHub Release com artefatos
        uses: softprops/action-gh-release@v2
        with:
          tag_name: v${{ env.VERSION }}
          name: "context7-cli v${{ env.VERSION }}"
          body: |
            ## context7-cli v${{ env.VERSION }}

            Pesquise documentação de qualquer biblioteca diretamente do terminal.
            Search any library's documentation directly from your terminal.

            ### Instalação / Installation

            **Via cargo (recomendado / recommended):**
            ```bash
            cargo install context7-cli
            ```

            **Download direto / Direct download:**

            | Plataforma / Platform | Arquivo / File |
            |---|---|
            | Linux x86_64 (glibc) | `context7-x86_64-unknown-linux-gnu.tar.gz` |
            | Linux x86_64 (musl/Alpine) | `context7-x86_64-unknown-linux-musl.tar.gz` |
            | macOS Universal (arm64+x86_64) | `context7-macos-universal.tar.gz` |
            | macOS arm64 | `context7-aarch64-apple-darwin.tar.gz` |
            | macOS x86_64 | `context7-x86_64-apple-darwin.tar.gz` |
            | Windows x86_64 | `context7-x86_64-pc-windows-msvc.zip` |
            | Flatpak (Linux) | `context7-cli.flatpak` |
            | Snap (Linux) | `context7-cli_*.snap` |
          draft: false
          prerelease: false
          files: |
            artifacts/**/*.tar.gz
            artifacts/**/*.zip
            artifacts/**/*.flatpak
            artifacts/**/*.snap
          generate_release_notes: false
          fail_on_unmatched_files: false

  publish-crates-io:
    name: Publicar no crates.io
    needs: [validate, build-matrix]
    runs-on: ubuntu-latest
    if: github.event_name == 'push' || (github.event_name == 'workflow_dispatch' && github.event.inputs.dry_run == 'false')
    permissions:
      contents: read
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Instalar toolchain Rust estável
        uses: dtolnay/rust-toolchain@stable

      - name: Cache de dependências Rust
        uses: Swatinem/rust-cache@v2
        with:
          shared-key: ubuntu-stable-publish

      - name: Publicar no crates.io
        run: cargo publish
        env:
          CARGO_REGISTRY_TOKEN: ${{ secrets.CRATES_IO_TOKEN }}