Skip to content

Commit 3168a65

Browse files
cursoragentenesify
andcommitted
ci: add GitHub Release builds and Cargo-free install docs
Add tag-triggered workflow to build stripped release binaries for Linux, macOS (x86_64 and aarch64), and Windows, package tar.gz/zip with README, aggregate SHA256SUMS, and publish via GitHub Releases. Add install-tw.sh for Linux/macOS to download and verify releases. Document prebuilt installs and tag/version alignment in README and guides. Co-authored-by: Enes Batur <enesbatur@protonmail.com>
1 parent 01fb6b5 commit 3168a65

5 files changed

Lines changed: 281 additions & 2 deletions

File tree

.github/workflows/release.yml

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
name: Release
2+
3+
on:
4+
push:
5+
tags:
6+
- "v*"
7+
8+
permissions:
9+
contents: write
10+
11+
jobs:
12+
build:
13+
strategy:
14+
fail-fast: false
15+
matrix:
16+
include:
17+
- os: ubuntu-latest
18+
target: x86_64-unknown-linux-gnu
19+
- os: macos-latest
20+
target: aarch64-apple-darwin
21+
- os: macos-latest
22+
target: x86_64-apple-darwin
23+
- os: windows-latest
24+
target: x86_64-pc-windows-msvc
25+
26+
runs-on: ${{ matrix.os }}
27+
steps:
28+
- uses: actions/checkout@v4
29+
30+
- uses: dtolnay/rust-toolchain@stable
31+
with:
32+
targets: ${{ matrix.target }}
33+
34+
- name: Build
35+
run: cargo build --release --locked --target ${{ matrix.target }}
36+
37+
- name: Package (Unix)
38+
if: runner.os != 'Windows'
39+
shell: bash
40+
env:
41+
VERSION: ${{ github.ref_name }}
42+
TARGET: ${{ matrix.target }}
43+
run: |
44+
set -euxo pipefail
45+
STAGING="staging/taskwal-${VERSION}-${TARGET}"
46+
mkdir -p "$STAGING"
47+
cp README.md "$STAGING/"
48+
strip "target/${TARGET}/release/tw" 2>/dev/null || true
49+
cp "target/${TARGET}/release/tw" "$STAGING/"
50+
chmod +x "$STAGING/tw"
51+
mkdir -p dist
52+
tar -czvf "dist/taskwal-${VERSION}-${TARGET}.tar.gz" -C staging "taskwal-${VERSION}-${TARGET}"
53+
54+
- name: Package (Windows)
55+
if: runner.os == 'Windows'
56+
shell: pwsh
57+
env:
58+
VERSION: ${{ github.ref_name }}
59+
TARGET: ${{ matrix.target }}
60+
run: |
61+
$ErrorActionPreference = "Stop"
62+
$staging = "staging/taskwal-$env:VERSION-$env:TARGET"
63+
New-Item -ItemType Directory -Force -Path $staging | Out-Null
64+
Copy-Item README.md $staging\
65+
Copy-Item "target/$env:TARGET/release/tw.exe" $staging\
66+
New-Item -ItemType Directory -Force -Path dist | Out-Null
67+
Compress-Archive -Path $staging -DestinationPath "dist/taskwal-$env:VERSION-$env:TARGET.zip" -Force
68+
69+
- uses: actions/upload-artifact@v4
70+
with:
71+
name: dist-${{ matrix.target }}
72+
path: dist/taskwal-*.*
73+
74+
release:
75+
needs: build
76+
runs-on: ubuntu-latest
77+
steps:
78+
- uses: actions/download-artifact@v4
79+
with:
80+
pattern: dist-*
81+
path: assets
82+
merge-multiple: true
83+
84+
- name: SHA256 checksums
85+
run: |
86+
cd assets
87+
sha256sum taskwal-* > SHA256SUMS
88+
cat SHA256SUMS
89+
90+
- uses: softprops/action-gh-release@v2
91+
with:
92+
generate_release_notes: true
93+
files: |
94+
assets/*

README.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,36 @@ For every subcommand, flag, and TUI key, see the full guides: **[docs/USAGE.md](
3434

3535
## Installation
3636

37+
### Prebuilt binaries
38+
39+
You do **not** need Rust or Cargo to run TaskWAL. Prebuilt `tw` binaries are attached to [GitHub Releases](https://github.com/enesify/taskwal/releases) for:
40+
41+
- Linux x86_64 (`x86_64-unknown-linux-gnu`, typical glibc-based distros)
42+
- macOS Intel and Apple Silicon (`x86_64-apple-darwin`, `aarch64-apple-darwin`)
43+
- Windows x86_64 (`x86_64-pc-windows-msvc`)
44+
45+
**Linux / macOS — install script** (default install dir: `~/.local/bin`):
46+
47+
```bash
48+
curl -fsSL https://raw.githubusercontent.com/enesify/taskwal/master/scripts/install-tw.sh | bash
49+
```
50+
51+
System-wide install (e.g. `/usr/local/bin`):
52+
53+
```bash
54+
curl -fsSL https://raw.githubusercontent.com/enesify/taskwal/master/scripts/install-tw.sh | TASKWAL_PREFIX=/usr/local bash
55+
```
56+
57+
Optional: `TASKWAL_REPO=owner/repo`, `TASKWAL_VERSION=v0.1.0` to pin a release.
58+
59+
**Windows — manual install:** download `taskwal-<tag>-x86_64-pc-windows-msvc.zip` from Releases, verify `SHA256SUMS`, extract `tw.exe`, and place it on your `PATH`.
60+
61+
**Manual (any platform):** download the matching `taskwal-<tag>-<target>.tar.gz` or `.zip`, verify checksums in `SHA256SUMS`, extract the `tw` binary, and move it to a directory on your `PATH`.
62+
63+
**Maintainers:** create a release by pushing a git tag `vX.Y.Z` that matches the `version` in [`Cargo.toml`](Cargo.toml) (for example tag `v0.1.0` for `version = "0.1.0"`). The release workflow builds and uploads archives plus `SHA256SUMS`.
64+
65+
### Build from source
66+
3767
Requires [Rust](https://rustup.rs/) 1.70+.
3868

3969
**Build** (binary at `target/release/tw`):

docs/KULLANIM.md

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,21 @@ TaskWAL, görevlerinizi **yerel bilgisayarınızda** tutan bir iş takip aracıd
2323

2424
## Kurulum ve `tw` komutu
2525

26-
Projeyi derledikten sonra:
26+
### Önceden derlenmiş ikili (Rust gerekmez)
27+
28+
Sürümler [GitHub Releases](https://github.com/enesify/taskwal/releases) üzerindedir; her sürümde hedefe göre arşivler ve `SHA256SUMS` dosyası bulunur.
29+
30+
**Linux / macOS** — isteğe bağlı kurulum betiği (depodaki `scripts/install-tw.sh`):
31+
32+
```bash
33+
curl -fsSL https://raw.githubusercontent.com/enesify/taskwal/master/scripts/install-tw.sh | bash
34+
```
35+
36+
**Windows**`taskwal-<sürüm>-x86_64-pc-windows-msvc.zip` dosyasını indirin; `tw.exe` dosyasını `PATH` üzerinde bir konuma çıkarın.
37+
38+
### Kaynak koddan (Cargo)
39+
40+
Projeyi klonladıktan sonra:
2741

2842
```bash
2943
cargo install --path /proje/yolu --force

docs/USAGE.md

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,21 @@ Override with environment variable:
1919

2020
## Install and the `tw` command
2121

22-
After building the project:
22+
### Prebuilt binary (no Rust)
23+
24+
Download a release from [GitHub Releases](https://github.com/enesify/taskwal/releases). Each release includes archives per target and a `SHA256SUMS` file.
25+
26+
**Linux / macOS** — optional install script (see repository `scripts/install-tw.sh`):
27+
28+
```bash
29+
curl -fsSL https://raw.githubusercontent.com/enesify/taskwal/master/scripts/install-tw.sh | bash
30+
```
31+
32+
**Windows** — use the `taskwal-<version>-x86_64-pc-windows-msvc.zip` asset; extract `tw.exe` onto your `PATH`.
33+
34+
### From source (Cargo)
35+
36+
After cloning the project:
2337

2438
```bash
2539
cargo install --path /path/to/taskwal --force

scripts/install-tw.sh

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
#!/usr/bin/env bash
2+
# Install the `tw` binary from GitHub Releases (no Rust/Cargo required).
3+
# Usage:
4+
# curl -fsSL https://raw.githubusercontent.com/OWNER/REPO/BRANCH/scripts/install-tw.sh | bash
5+
# Optional environment:
6+
# TASKWAL_REPO=owner/repo (default: enesify/taskwal)
7+
# TASKWAL_VERSION=v0.1.0 (default: latest GitHub release)
8+
# TASKWAL_PREFIX=/usr/local (install to $PREFIX/bin; default: ~/.local)
9+
10+
set -euo pipefail
11+
12+
TASKWAL_REPO="${TASKWAL_REPO:-enesify/taskwal}"
13+
TASKWAL_VERSION="${TASKWAL_VERSION:-}"
14+
TASKWAL_PREFIX="${TASKWAL_PREFIX:-}"
15+
16+
die() {
17+
echo "install-tw.sh: $*" >&2
18+
exit 1
19+
}
20+
21+
detect_target_triple() {
22+
local os arch
23+
os="$(uname -s)"
24+
arch="$(uname -m)"
25+
case "$os" in
26+
Linux)
27+
case "$arch" in
28+
x86_64) echo "x86_64-unknown-linux-gnu" ;;
29+
aarch64 | arm64) die "no prebuilt binary for Linux $arch yet; build from source with Rust" ;;
30+
*) die "unsupported Linux architecture: $arch" ;;
31+
esac
32+
;;
33+
Darwin)
34+
case "$arch" in
35+
x86_64) echo "x86_64-apple-darwin" ;;
36+
arm64) echo "aarch64-apple-darwin" ;;
37+
*) die "unsupported macOS architecture: $arch" ;;
38+
esac
39+
;;
40+
*)
41+
die "unsupported OS: $os (install the Windows zip from Releases, or build from source)"
42+
;;
43+
esac
44+
}
45+
46+
require_cmd() {
47+
command -v "$1" >/dev/null 2>&1 || die "required command not found: $1"
48+
}
49+
50+
download_to() {
51+
local url="$1" out="$2"
52+
if command -v curl >/dev/null 2>&1; then
53+
curl -fsSL -o "$out" "$url"
54+
elif command -v wget >/dev/null 2>&1; then
55+
wget -q -O "$out" "$url"
56+
else
57+
die "need curl or wget to download"
58+
fi
59+
}
60+
61+
fetch_latest_tag() {
62+
local api_base="$1" json
63+
json="$(curl -fsSL "${api_base}/releases/latest")"
64+
if command -v python3 >/dev/null 2>&1; then
65+
printf '%s' "$json" | python3 -c "import sys,json; print(json.load(sys.stdin)['tag_name'])"
66+
return
67+
fi
68+
require_cmd grep
69+
require_cmd sed
70+
printf '%s' "$json" | sed -n 's/.*"tag_name"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p' | head -1
71+
}
72+
73+
main() {
74+
require_cmd uname
75+
local triple
76+
triple="$(detect_target_triple)"
77+
78+
local api_base="https://api.github.com/repos/${TASKWAL_REPO}"
79+
local tag asset_name tmpdir install_dir
80+
81+
if [[ -n "$TASKWAL_VERSION" ]]; then
82+
tag="$TASKWAL_VERSION"
83+
else
84+
tag="$(fetch_latest_tag "$api_base")"
85+
[[ -n "$tag" ]] || die "could not determine latest release tag"
86+
fi
87+
88+
asset_name="taskwal-${tag}-${triple}.tar.gz"
89+
90+
if [[ -n "$TASKWAL_PREFIX" ]]; then
91+
install_dir="${TASKWAL_PREFIX%/}/bin"
92+
else
93+
install_dir="${HOME}/.local/bin"
94+
fi
95+
96+
tmpdir="$(mktemp -d "${TMPDIR:-/tmp}/taskwal-install.XXXXXX")"
97+
trap 'rm -rf "$tmpdir"' EXIT
98+
99+
local sums_url="https://github.com/${TASKWAL_REPO}/releases/download/${tag}/SHA256SUMS"
100+
local asset_url="https://github.com/${TASKWAL_REPO}/releases/download/${tag}/${asset_name}"
101+
102+
echo "Downloading ${asset_name} ..."
103+
download_to "$sums_url" "${tmpdir}/SHA256SUMS"
104+
download_to "$asset_url" "${tmpdir}/${asset_name}"
105+
106+
(
107+
cd "$tmpdir"
108+
grep -F "${asset_name}" SHA256SUMS | sha256sum -c
109+
tar -xzf "${asset_name}"
110+
local inner="taskwal-${tag}-${triple}/tw"
111+
[[ -f "$inner" ]] || die "expected ${inner} inside archive"
112+
chmod +x "$inner"
113+
mkdir -p "$install_dir"
114+
mv "$inner" "${install_dir}/tw"
115+
)
116+
117+
echo "Installed tw to ${install_dir}/tw"
118+
case ":${PATH}:" in
119+
*":${install_dir}:"*) ;;
120+
*)
121+
echo "Add ${install_dir} to your PATH, e.g.:"
122+
echo " export PATH=\"${install_dir}:\$PATH\""
123+
;;
124+
esac
125+
}
126+
127+
main "$@"

0 commit comments

Comments
 (0)