Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
123 changes: 123 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
name: Release

on:
release:
types:
- published
workflow_dispatch:

permissions:
contents: write

concurrency:
group: release-${{ github.workflow }}-${{ github.event.release.tag_name || github.ref }}
cancel-in-progress: false

jobs:
build:
name: Build Release Artifacts
runs-on: ubuntu-latest
timeout-minutes: 20
strategy:
fail-fast: false
matrix:
include:
- goos: linux
goarch: amd64
archive_ext: tar.gz
- goos: linux
goarch: arm64
archive_ext: tar.gz
- goos: darwin
goarch: amd64
archive_ext: tar.gz
- goos: darwin
goarch: arm64
archive_ext: tar.gz
- goos: windows
goarch: amd64
archive_ext: zip
- goos: windows
goarch: arm64
archive_ext: zip

steps:
- name: Checkout repository
uses: actions/checkout@v6
with:
persist-credentials: false

- name: Set up Go
uses: actions/setup-go@v6
with:
go-version-file: go.mod

- name: Build archive
shell: bash
env:
BINARY: flare-edge-cli
GOOS: ${{ matrix.goos }}
GOARCH: ${{ matrix.goarch }}
ARCHIVE_EXT: ${{ matrix.archive_ext }}
TAG: ${{ github.event.release.tag_name || github.ref_name }}
run: |
set -euo pipefail

version="${TAG#refs/tags/}"
staging_dir="dist/${BINARY}_${version}_${GOOS}_${GOARCH}"
archive_base="${BINARY}_${version}_${GOOS}_${GOARCH}"
binary_name="${BINARY}"

if [ "${GOOS}" = "windows" ]; then
binary_name="${binary_name}.exe"
fi

mkdir -p "${staging_dir}"
GOOS="${GOOS}" GOARCH="${GOARCH}" CGO_ENABLED=0 go build -trimpath -ldflags="-s -w" -o "${staging_dir}/${binary_name}" ./cmd/flare-edge-cli
cp LICENSE README.md "${staging_dir}/"

pushd dist >/dev/null
if [ "${ARCHIVE_EXT}" = "zip" ]; then
zip -rq "${archive_base}.zip" "${archive_base}"
else
tar -czf "${archive_base}.tar.gz" "${archive_base}"
fi
popd >/dev/null

- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: release-${{ matrix.goos }}-${{ matrix.goarch }}
path: |
dist/*.tar.gz
dist/*.zip
if-no-files-found: error

publish:
name: Publish Release Assets
needs: build
runs-on: ubuntu-latest
timeout-minutes: 10

steps:
- name: Download artifacts
uses: actions/download-artifact@v5
with:
path: dist
pattern: release-*
merge-multiple: true

- name: Generate checksums
shell: bash
run: |
set -euo pipefail
cd dist
shasum -a 256 *.tar.gz *.zip > checksums.txt

- name: Upload release assets
uses: softprops/action-gh-release@v2
with:
files: |
dist/*.tar.gz
dist/*.zip
dist/checksums.txt
21 changes: 20 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,26 @@ The implementation is intentionally biased toward agent use:

## Install

Build the binary from the repository root:
One-liner installer for Linux and macOS:

```bash
curl -fsSL https://raw.githubusercontent.com/Gladium-AI/flare-edge-cli/main/install.sh | sh
```

The installer detects your OS and CPU architecture, downloads the latest GitHub release archive, and installs `flare-edge-cli` into a user-local bin directory. It prefers `INSTALL_DIR` when set, then `XDG_BIN_HOME`, then `~/.local/bin`, then `~/bin`.

Prebuilt release archives are attached automatically for:

- `linux/amd64`
- `linux/arm64`
- `darwin/amd64`
- `darwin/arm64`
- `windows/amd64`
- `windows/arm64`

Release downloads are published on the [GitHub Releases](https://github.com/Gladium-AI/flare-edge-cli/releases) page.

Build from source from the repository root:

```bash
make build
Expand Down
124 changes: 124 additions & 0 deletions install.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
#!/bin/sh
set -eu

REPO="${REPO:-Gladium-AI/flare-edge-cli}"
BINARY="${BINARY:-flare-edge-cli}"

resolve_install_dir() {
if [ -n "${INSTALL_DIR:-}" ]; then
printf '%s\n' "${INSTALL_DIR}"
return
fi

if [ -n "${XDG_BIN_HOME:-}" ]; then
printf '%s\n' "${XDG_BIN_HOME}"
return
fi

if [ -d "${HOME}/.local/bin" ]; then
printf '%s\n' "${HOME}/.local/bin"
return
fi

if [ -d "${HOME}/bin" ]; then
printf '%s\n' "${HOME}/bin"
return
fi

printf '%s\n' "${HOME}/.local/bin"
}

detect_platform() {
case "$(uname -s)" in
Linux*)
GOOS="linux"
;;
Darwin*)
GOOS="darwin"
;;
*)
echo "Unsupported OS: $(uname -s)" >&2
exit 1
;;
esac

case "$(uname -m)" in
x86_64|amd64)
GOARCH="amd64"
;;
arm64|aarch64)
GOARCH="arm64"
;;
*)
echo "Unsupported architecture: $(uname -m)" >&2
exit 1
;;
esac
}

fetch_latest_tag() {
api_url="https://api.github.com/repos/${REPO}/releases/latest"

if command -v curl >/dev/null 2>&1; then
curl -fsSL "${api_url}" | sed -n 's/.*"tag_name": *"\([^"]*\)".*/\1/p' | head -n 1
return
fi

if command -v wget >/dev/null 2>&1; then
wget -qO- "${api_url}" | sed -n 's/.*"tag_name": *"\([^"]*\)".*/\1/p' | head -n 1
return
fi

echo "Error: curl or wget is required" >&2
exit 1
}

download_archive() {
url="$1"
out="$2"

if command -v curl >/dev/null 2>&1; then
curl -fsSL "${url}" -o "${out}"
return
fi

wget -q "${url}" -O "${out}"
}

INSTALL_DIR="$(resolve_install_dir)"
detect_platform

echo "Detected platform: ${GOOS}/${GOARCH}"

TAG="${TAG:-$(fetch_latest_tag)}"
if [ -z "${TAG}" ]; then
echo "Error: could not determine latest release tag" >&2
exit 1
fi

ARCHIVE="${BINARY}_${TAG}_${GOOS}_${GOARCH}.tar.gz"
URL="https://github.com/${REPO}/releases/download/${TAG}/${ARCHIVE}"
TMPDIR="$(mktemp -d)"
trap 'rm -rf "${TMPDIR}"' EXIT INT TERM

echo "Latest release: ${TAG}"
echo "Downloading ${URL}"
download_archive "${URL}" "${TMPDIR}/${ARCHIVE}"

tar -xzf "${TMPDIR}/${ARCHIVE}" -C "${TMPDIR}"
EXTRACTED_DIR="${TMPDIR}/${BINARY}_${TAG}_${GOOS}_${GOARCH}"

mkdir -p "${INSTALL_DIR}"
install -m 0755 "${EXTRACTED_DIR}/${BINARY}" "${INSTALL_DIR}/${BINARY}"

echo "Installed ${BINARY} ${TAG} to ${INSTALL_DIR}/${BINARY}"

case ":${PATH}:" in
*":${INSTALL_DIR}:"*)
;;
*)
echo
echo "Add ${INSTALL_DIR} to your PATH:"
echo " export PATH=\"${INSTALL_DIR}:\$PATH\""
;;
esac
Loading