diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..5f1d0e2 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,152 @@ +name: Release + +on: + push: + tags: + - "v*" + workflow_dispatch: + +permissions: + contents: write + +env: + CARGO_TERM_COLOR: always + +jobs: + build-release: + name: Build (${{ matrix.target }}) + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + include: + - target: x86_64-unknown-linux-gnu + os: ubuntu-latest + use_cross: false + archive_name: brokecrew-${{ github.ref_name }}-x86_64-unknown-linux-gnu.tar.gz + + - target: aarch64-unknown-linux-gnu + os: ubuntu-latest + use_cross: true + archive_name: brokecrew-${{ github.ref_name }}-aarch64-unknown-linux-gnu.tar.gz + + - target: x86_64-apple-darwin + os: macos-13 + use_cross: false + archive_name: brokecrew-${{ github.ref_name }}-x86_64-apple-darwin.tar.gz + + - target: aarch64-apple-darwin + os: macos-latest + use_cross: false + archive_name: brokecrew-${{ github.ref_name }}-aarch64-apple-darwin.tar.gz + + - target: x86_64-pc-windows-msvc + os: windows-latest + use_cross: false + archive_name: brokecrew-${{ github.ref_name }}-x86_64-pc-windows-msvc.zip + + steps: + - name: Checkout source + uses: actions/checkout@v4 + + - name: Install Rust toolchain + uses: dtolnay/rust-toolchain@stable + with: + targets: ${{ matrix.target }} + + - name: Install Cross for cross-compilation + if: matrix.use_cross + run: cargo install cross --git https://github.com/cross-rs/cross + + - name: Build release binary + run: | + if [ "${{ matrix.use_cross }}" = "true" ]; then + cross build --release --target ${{ matrix.target }} + else + cargo build --release --target ${{ matrix.target }} + fi + shell: bash + + - name: Package artifacts (Unix) + if: runner.os != 'Windows' + run: | + BIN_PATH="target/${{ matrix.target }}/release/brokecrew" + STAGING="brokecrew-staging" + mkdir -p "$STAGING" + cp "$BIN_PATH" "$STAGING/brokecrew" + cp README.md LICENSE-MIT LICENSE-APACHE "$STAGING/" + mkdir -p "$STAGING/config" + cp config/personas.example.toml "$STAGING/config/" + tar -czvf "${{ matrix.archive_name }}" -C "$STAGING" . + shell: bash + + - name: Package artifacts (Windows) + if: runner.os == 'Windows' + run: | + $bin = "target/${{ matrix.target }}/release/brokecrew.exe" + $staging = "brokecrew-staging" + New-Item -ItemType Directory -Force -Path $staging + Copy-Item $bin -Destination "$staging/brokecrew.exe" + Copy-Item README.md, LICENSE-MIT, LICENSE-APACHE -Destination "$staging/" + New-Item -ItemType Directory -Force -Path "$staging/config" + Copy-Item config/personas.example.toml -Destination "$staging/config/" + Compress-Archive -Path "$staging/*" -DestinationPath "${{ matrix.archive_name }}" + shell: pwsh + + - name: Generate SHA256 checksum + run: | + if [ "${{ runner.os }}" = "Windows" ]; then + CertUtil -hashfile "${{ matrix.archive_name }}" SHA256 | Select-String -Pattern "^[a-f0-9]" | ForEach-Object { "$($_.Line.Trim()) ${{ matrix.archive_name }}" } > "${{ matrix.archive_name }}.sha256" + else + shasum -a 256 "${{ matrix.archive_name }}" > "${{ matrix.archive_name }}.sha256" + fi + shell: bash + + - name: Upload artifacts + uses: actions/upload-artifact@v4 + with: + name: assets-${{ matrix.target }} + path: | + ${{ matrix.archive_name }} + ${{ matrix.archive_name }}.sha256 + + publish-release: + name: Publish GitHub Release + needs: [build-release] + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Download all built artifacts + uses: actions/download-artifact@v4 + with: + path: dist + merge-multiple: true + + - name: Create Release and Upload Assets + uses: softprops/action-gh-release@v2 + with: + files: | + dist/* + generate_release_notes: true + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + publish-crates: + name: Publish to Crates.io + needs: [build-release] + runs-on: ubuntu-latest + if: startsWith(github.ref, 'refs/tags/v') + steps: + - name: Checkout source + uses: actions/checkout@v4 + + - name: Install Rust toolchain + uses: dtolnay/rust-toolchain@stable + + - name: Publish to crates.io + if: env.CARGO_REGISTRY_TOKEN != '' + run: cargo publish --token "$CARGO_REGISTRY_TOKEN" + env: + CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} diff --git a/Cargo.toml b/Cargo.toml index 5055fb1..a9c15d6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,7 +6,7 @@ authors = ["oiupoyt "] description = "A Rust-native multi-model AI team CLI with resilient OpenRouter fallback routing" license = "MIT OR Apache-2.0" readme = "README.md" -repository = "https://github.com/brokecrew/brokecrew" +repository = "https://github.com/oiupoyt/brokecrew" keywords = ["cli", "llm", "openrouter", "multi-agent", "ai"] categories = ["command-line-utilities", "development-tools"] diff --git a/README.md b/README.md index 485c465..652f958 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # BrokeCrew 🤖⚡ -[![CI](https://github.com/brokecrew/brokecrew/actions/workflows/ci.yml/badge.svg)](https://github.com/brokecrew/brokecrew/actions) +[![CI](https://github.com/oiupoyt/brokecrew/actions/workflows/ci.yml/badge.svg)](https://github.com/oiupoyt/brokecrew/actions) [![License](https://img.shields.io/badge/license-MIT%20OR%20Apache--2.0-blue.svg)](LICENSE-MIT) [![Crates.io](https://img.shields.io/crates/v/brokecrew.svg)](https://crates.io/crates/brokecrew) @@ -47,13 +47,19 @@ Code Review: ### 1. Installation +**One-line curl install (Linux & macOS):** +```bash +curl -fsSL https://raw.githubusercontent.com/oiupoyt/brokecrew/main/install.sh | bash +``` + +**Via Cargo (Crates.io):** ```bash cargo install brokecrew ``` -Or build from source: +**Build from source:** ```bash -git clone https://github.com/brokecrew/brokecrew.git +git clone https://github.com/oiupoyt/brokecrew.git cd brokecrew cargo install --path . ``` diff --git a/install.sh b/install.sh new file mode 100755 index 0000000..8bd4324 --- /dev/null +++ b/install.sh @@ -0,0 +1,143 @@ +#!/usr/bin/env bash +# BrokeCrew Installer +# Usage: curl -fsSL https://raw.githubusercontent.com/oiupoyt/brokecrew/main/install.sh | bash + +set -euo pipefail + +REPO="oiupoyt/brokecrew" +BINARY_NAME="brokecrew" + +# ANSI Color codes +BOLD="\033[1m" +GREEN="\033[0;32m" +CYAN="\033[0;36m" +YELLOW="\033[0;33m" +RED="\033[0;31m" +RESET="\033[0m" + +log_info() { + printf "${CYAN}==>${RESET} ${BOLD}%b${RESET}\n" "$1" +} + +log_success() { + printf "${GREEN}✔${RESET} ${BOLD}%b${RESET}\n" "$1" +} + +log_warn() { + printf "${YELLOW}⚠ %b${RESET}\n" "$1" +} + +log_error() { + printf "${RED}✖ Error: %b${RESET}\n" "$1" >&2 +} + +# 1. Detect Operating System +OS="$(uname -s | tr '[:upper:]' '[:lower:]')" +case "$OS" in + linux) + TARGET_OS="unknown-linux-gnu" + ;; + darwin) + TARGET_OS="apple-darwin" + ;; + *) + log_error "Unsupported operating system: $OS. BrokeCrew supports Linux and macOS via this script." + exit 1 + ;; +esac + +# 2. Detect CPU Architecture +ARCH="$(uname -m)" +case "$ARCH" in + x86_64|amd64) + TARGET_ARCH="x86_64" + ;; + aarch64|arm64) + TARGET_ARCH="aarch64" + ;; + *) + log_error "Unsupported CPU architecture: $ARCH. BrokeCrew prebuilts support x86_64 and aarch64." + exit 1 + ;; +esac + +TARGET="${TARGET_ARCH}-${TARGET_OS}" +log_info "Detected platform: ${BOLD}${TARGET}${RESET}" + +# 3. Determine Installation Directory +if [ -n "${INSTALL_DIR:-}" ]; then + DEST_DIR="$INSTALL_DIR" +elif [ -d "$HOME/.cargo/bin" ] && [[ ":$PATH:" == *":$HOME/.cargo/bin:"* ]]; then + DEST_DIR="$HOME/.cargo/bin" +elif [ -d "$HOME/.local/bin" ]; then + DEST_DIR="$HOME/.local/bin" +else + DEST_DIR="$HOME/.local/bin" +fi + +mkdir -p "$DEST_DIR" + +# 4. Resolve Latest Version from GitHub +log_info "Resolving latest release for ${REPO}..." +LATEST_TAG=$(curl -sSL "https://api.github.com/repos/${REPO}/releases/latest" 2>/dev/null | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/' || true) + +if [ -z "$LATEST_TAG" ]; then + LATEST_TAG="v0.1.0" + log_warn "Could not resolve latest tag from GitHub API, defaulting to ${LATEST_TAG}" +fi + +ARCHIVE_NAME="brokecrew-${LATEST_TAG}-${TARGET}.tar.gz" +DOWNLOAD_URL="https://github.com/${REPO}/releases/download/${LATEST_TAG}/${ARCHIVE_NAME}" + +TMP_DIR=$(mktemp -d -t brokecrew-install-XXXXXX) +cleanup() { + rm -rf "$TMP_DIR" +} +trap cleanup EXIT + +# 5. Download & Extract +log_info "Downloading BrokeCrew (${LATEST_TAG}) for ${TARGET}..." +DOWNLOAD_SUCCESS=false + +if curl -sSL -f -o "${TMP_DIR}/${ARCHIVE_NAME}" "$DOWNLOAD_URL"; then + DOWNLOAD_SUCCESS=true + tar -xzf "${TMP_DIR}/${ARCHIVE_NAME}" -C "$TMP_DIR" + INSTALL_SRC="${TMP_DIR}/${BINARY_NAME}" +fi + +# Fallback to cargo install if release asset not yet published +if [ "$DOWNLOAD_SUCCESS" = false ]; then + log_warn "Precompiled release asset not found at ${DOWNLOAD_URL}." + if command -v cargo >/dev/null 2>&1; then + log_info "Building from source via cargo..." + cargo install --git "https://github.com/${REPO}.git" --root "${TMP_DIR}/cargo-install" + INSTALL_SRC="${TMP_DIR}/cargo-install/bin/${BINARY_NAME}" + else + log_error "No prebuilt binary available and cargo is not installed." + log_info "Please install Rust (https://rustup.rs) or download a binary manually from https://github.com/${REPO}/releases" + exit 1 + fi +fi + +# 6. Install Executable +chmod +x "$INSTALL_SRC" +cp -f "$INSTALL_SRC" "${DEST_DIR}/${BINARY_NAME}" + +log_success "Installed '${BINARY_NAME}' into ${DEST_DIR}/${BINARY_NAME}" + +# 7. PATH Verification +if [[ ":$PATH:" != *":$DEST_DIR:"* ]]; then + log_warn "${DEST_DIR} is not in your system PATH." + printf "Add the following line to your ~/.bashrc or ~/.zshrc:\n" + printf " export PATH=\"%s:\$PATH\"\n\n" "$DEST_DIR" +fi + +# 8. Success Banner +printf "\n" +printf "${GREEN}${BOLD}BrokeCrew successfully installed!${RESET}\n\n" +printf "Run the command:\n" +printf " ${CYAN}${BOLD}brokecrew --help${RESET}\n\n" +printf "To set up your OpenRouter API key:\n" +printf " ${CYAN}${BOLD}brokecrew config set-key${RESET}\n\n" +printf "To start chatting with your AI personas:\n" +printf " ${CYAN}${BOLD}brokecrew chat \"build me a proxy checker site\"${RESET}\n\n"