Skip to content

Commit 6d6dcd7

Browse files
committed
feat: publish release binaries and simplify native install
1 parent 174d353 commit 6d6dcd7

2 files changed

Lines changed: 289 additions & 9 deletions

File tree

‎.github/workflows/release.yml‎

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
name: 发布 Release(预编译二进制)
2+
3+
on:
4+
push:
5+
tags:
6+
- "v*"
7+
workflow_dispatch:
8+
inputs:
9+
tag:
10+
description: "Tag to release (e.g. v0.2.0)"
11+
required: true
12+
type: string
13+
14+
permissions:
15+
contents: write
16+
17+
jobs:
18+
build:
19+
name: 构建二进制
20+
runs-on: ubuntu-latest
21+
strategy:
22+
fail-fast: false
23+
matrix:
24+
goos: [linux, darwin, windows]
25+
goarch: [amd64, arm64]
26+
steps:
27+
- name: 检出代码
28+
uses: actions/checkout@v4
29+
with:
30+
ref: ${{ github.event_name == 'workflow_dispatch' && inputs.tag || github.ref }}
31+
32+
- name: 安装 Go
33+
uses: actions/setup-go@v5
34+
with:
35+
go-version: "1.24.x"
36+
cache: true
37+
38+
- name: 构建(CGO=0)
39+
env:
40+
GOOS: ${{ matrix.goos }}
41+
GOARCH: ${{ matrix.goarch }}
42+
CGO_ENABLED: "0"
43+
VG_TAG: ${{ github.event_name == 'workflow_dispatch' && inputs.tag || github.ref_name }}
44+
run: |
45+
set -euo pipefail
46+
47+
mkdir -p dist
48+
49+
commit="$(git rev-parse HEAD)"
50+
build_date="$(date -u +'%Y-%m-%dT%H:%M:%SZ')"
51+
ldflags="-s -w \
52+
-X github.com/inkdust2021/vibeguard/internal/version.Version=${VG_TAG} \
53+
-X github.com/inkdust2021/vibeguard/internal/version.GitCommit=${commit} \
54+
-X github.com/inkdust2021/vibeguard/internal/version.BuildDate=${build_date}"
55+
56+
bin="vibeguard"
57+
if [[ "${GOOS}" == "windows" ]]; then
58+
bin="vibeguard.exe"
59+
fi
60+
61+
go build -trimpath -buildvcs=false -ldflags "${ldflags}" -o "${bin}" ./cmd/vibeguard
62+
63+
if [[ "${GOOS}" == "windows" ]]; then
64+
zip -9 "vibeguard_windows_${GOARCH}.zip" "${bin}"
65+
else
66+
tar -czf "vibeguard_${GOOS}_${GOARCH}.tar.gz" "${bin}"
67+
fi
68+
69+
- name: 上传构建产物
70+
uses: actions/upload-artifact@v4
71+
with:
72+
name: dist-${{ matrix.goos }}-${{ matrix.goarch }}
73+
path: |
74+
vibeguard_*.tar.gz
75+
vibeguard_*.zip
76+
77+
release:
78+
name: 发布 Release
79+
runs-on: ubuntu-latest
80+
needs: build
81+
steps:
82+
- name: 下载构建产物
83+
uses: actions/download-artifact@v4
84+
with:
85+
path: artifacts
86+
87+
- name: 准备校验文件
88+
run: |
89+
set -euo pipefail
90+
91+
mkdir -p out
92+
find artifacts -type f \( -name "vibeguard_*.tar.gz" -o -name "vibeguard_*.zip" \) -exec cp {} out/ \;
93+
94+
(cd out && sha256sum vibeguard_* > checksums.txt)
95+
96+
- name: 创建/更新 Release 并上传资产
97+
uses: softprops/action-gh-release@v2
98+
with:
99+
tag_name: ${{ github.event_name == 'workflow_dispatch' && inputs.tag || github.ref_name }}
100+
generate_release_notes: true
101+
files: |
102+
out/*

‎install.sh‎

Lines changed: 187 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ set -euo pipefail
44
# VibeGuard 安装脚本(中英双语) / VibeGuard installer (ZH/EN)
55
#
66
# 功能 / Features:
7-
# - 安装 vibeguard 二进制(优先从源码构建,其次 go install) / Install vibeguard (build from source or go install)
7+
# - 安装 vibeguard 二进制(优先下载 Release 预编译,其次从源码构建,再次 go install) / Install vibeguard (prefer Release binaries; fallback to source build; then go install)
88
# - 导出(“下载”)系统信任所需的 CA 证书到文件 / Export ("download") the CA certificate to a file
99
# - 可选:安装 CA 到系统信任库(会触发 sudo) / Optional: install CA into system trust store (will invoke sudo)
1010
#
@@ -75,6 +75,166 @@ in_repo() {
7575
[[ -f "go.mod" && -f "cmd/vibeguard/main.go" ]]
7676
}
7777

78+
normalize_version() {
79+
# 允许输入 0.2.0 / v0.2.0 / latest
80+
local v="${1:-}"
81+
v="$(echo "${v}" | tr -d '[:space:]')"
82+
if [[ -z "${v}" || "${v}" == "latest" ]]; then
83+
echo "latest"
84+
return 0
85+
fi
86+
case "${v}" in
87+
v*) echo "${v}" ;;
88+
*) echo "v${v}" ;;
89+
esac
90+
}
91+
92+
detect_goos() {
93+
local os_name
94+
os_name="$(uname -s 2>/dev/null || true)"
95+
case "${os_name}" in
96+
Darwin) echo "darwin" ;;
97+
Linux) echo "linux" ;;
98+
*) echo "" ;;
99+
esac
100+
}
101+
102+
detect_goarch() {
103+
local arch
104+
arch="$(uname -m 2>/dev/null || true)"
105+
case "${arch}" in
106+
x86_64|amd64) echo "amd64" ;;
107+
arm64|aarch64) echo "arm64" ;;
108+
*) echo "" ;;
109+
esac
110+
}
111+
112+
download_file() {
113+
local url="${1:-}"
114+
local out="${2:-}"
115+
[[ -n "${url}" && -n "${out}" ]] || return 1
116+
if have curl; then
117+
curl -fsSL "${url}" -o "${out}"
118+
elif have wget; then
119+
wget -qO "${out}" "${url}"
120+
else
121+
return 1
122+
fi
123+
}
124+
125+
sha256_file() {
126+
local p="${1:-}"
127+
[[ -f "${p}" ]] || return 1
128+
if have sha256sum; then
129+
sha256sum "${p}" | awk '{print $1}'
130+
elif have shasum; then
131+
shasum -a 256 "${p}" | awk '{print $1}'
132+
elif have openssl; then
133+
openssl dgst -sha256 "${p}" | awk '{print $2}'
134+
else
135+
return 1
136+
fi
137+
}
138+
139+
install_vibeguard_from_release() {
140+
local install_dir="${1:-}"
141+
local repo="${2:-inkdust2021/VibeGuard}"
142+
local version="${3:-latest}"
143+
local verify="${4:-1}" # 1|0
144+
145+
[[ -n "${install_dir}" ]] || return 1
146+
version="$(normalize_version "${version}")"
147+
148+
local goos
149+
goos="$(detect_goos)"
150+
local goarch
151+
goarch="$(detect_goarch)"
152+
153+
if [[ -z "${goos}" || -z "${goarch}" ]]; then
154+
return 1
155+
fi
156+
157+
if [[ "${goos}" != "darwin" && "${goos}" != "linux" ]]; then
158+
return 1
159+
fi
160+
161+
if [[ "${goarch}" != "amd64" && "${goarch}" != "arm64" ]]; then
162+
return 1
163+
fi
164+
165+
local base="https://github.com/${repo}/releases"
166+
local dl_base=""
167+
if [[ "${version}" == "latest" ]]; then
168+
dl_base="${base}/latest/download"
169+
else
170+
dl_base="${base}/download/${version}"
171+
fi
172+
173+
local asset="vibeguard_${goos}_${goarch}.tar.gz"
174+
local url_asset="${dl_base}/${asset}"
175+
local url_sum="${dl_base}/checksums.txt"
176+
177+
say "安装 vibeguard(Release 预编译)" "Installing vibeguard (Release binary)"
178+
echo "$(t "仓库:" "Repo: ")${repo}"
179+
echo "$(t "版本:" "Version: ")${version}"
180+
echo "$(t "平台:" "Platform: ")${goos}/${goarch}"
181+
182+
if [[ "${verify}" == "1" ]]; then
183+
if ! (have sha256sum || have shasum || have openssl); then
184+
say "未检测到 sha256 校验工具:将跳过校验" "No sha256 tool found: verification will be skipped"
185+
verify="0"
186+
fi
187+
fi
188+
189+
(
190+
set -euo pipefail
191+
tmp="$(mktemp -d -t vibeguard-install.XXXXXX 2>/dev/null || mktemp -d "/tmp/vibeguard-install.XXXXXX")"
192+
trap 'rm -rf "$tmp"' EXIT
193+
194+
need tar
195+
196+
if ! download_file "${url_asset}" "${tmp}/${asset}"; then
197+
echo "$(t "下载失败:" "Download failed: ")${url_asset}" >&2
198+
exit 2
199+
fi
200+
201+
if [[ "${verify}" == "1" ]]; then
202+
if ! download_file "${url_sum}" "${tmp}/checksums.txt"; then
203+
echo "$(t "下载校验文件失败:" "Failed to download checksums: ")${url_sum}" >&2
204+
exit 3
205+
fi
206+
207+
expected="$(grep -E "[[:space:]]${asset}$" "${tmp}/checksums.txt" | awk '{print $1}' | head -n 1 || true)"
208+
if [[ -z "${expected}" ]]; then
209+
echo "$(t "校验文件中未找到条目:" "Checksums entry not found: ")${asset}" >&2
210+
exit 4
211+
fi
212+
213+
actual="$(sha256_file "${tmp}/${asset}" || true)"
214+
if [[ -z "${actual}" || "${actual}" != "${expected}" ]]; then
215+
echo "$(t "sha256 校验失败(可能被篡改或下载损坏)" "sha256 verification failed (possible tampering or corrupted download)")" >&2
216+
echo " expected=${expected}" >&2
217+
echo " actual=${actual}" >&2
218+
exit 5
219+
fi
220+
fi
221+
222+
tar -xzf "${tmp}/${asset}" -C "${tmp}"
223+
if [[ ! -f "${tmp}/vibeguard" ]]; then
224+
echo "$(t "解压后未找到 vibeguard 二进制" "vibeguard binary not found after extraction")" >&2
225+
exit 6
226+
fi
227+
228+
mkdir -p "${install_dir}"
229+
if have install; then
230+
install -m 0755 "${tmp}/vibeguard" "${install_dir}/vibeguard"
231+
else
232+
cp -f "${tmp}/vibeguard" "${install_dir}/vibeguard"
233+
chmod 0755 "${install_dir}/vibeguard" >/dev/null 2>&1 || true
234+
fi
235+
)
236+
}
237+
78238
# 交互检测:
79239
# - 当脚本通过管道执行(curl | bash)时,stdin 不是 TTY,但 /dev/tty 通常可用;
80240
# - 我们会在解析参数后尝试打开 /dev/tty 到 FD=3(VG_TTY_FD=3),以便继续交互。
@@ -781,13 +941,17 @@ PATH_MODE="auto" # auto|add|skip
781941
AUTOSTART_MODE="auto" # auto|add|skip
782942
NON_INTERACTIVE="0"
783943
INSTALL_METHOD="auto" # auto|native|docker
944+
INSTALL_VERSION="latest"
945+
VERIFY_RELEASE="1"
784946

785947
while [[ $# -gt 0 ]]; do
786948
case "$1" in
787949
--dir)
788950
INSTALL_DIR="${2:-}"; shift 2;;
789951
--method)
790952
INSTALL_METHOD="${2:-}"; shift 2;;
953+
--version)
954+
INSTALL_VERSION="${2:-}"; shift 2;;
791955
--trust)
792956
TRUST_MODE="${2:-}"; TRUST_MODE_SET="1"; shift 2;;
793957
--export)
@@ -798,6 +962,8 @@ while [[ $# -gt 0 ]]; do
798962
PATH_MODE="${2:-}"; shift 2;;
799963
--autostart)
800964
AUTOSTART_MODE="${2:-}"; shift 2;;
965+
--no-verify)
966+
VERIFY_RELEASE="0"; shift 1;;
801967
--non-interactive)
802968
NON_INTERACTIVE="1"; shift 1;;
803969
-h|--help)
@@ -807,11 +973,13 @@ VibeGuard 安装脚本 / Installer
807973
参数 / Options:
808974
--dir DIR 安装目录 / Install dir (default: $HOME/.local/bin)
809975
--method METHOD auto|native|docker (default: auto)
976+
--version VERSION 安装版本:latest|vX.Y.Z(native 会优先下载 Release) / Version: latest|vX.Y.Z (native prefers Release)
810977
--trust MODE system|user|auto|skip (default: system)
811978
--export 导出 CA 证书到文件 / Export CA cert to a file
812979
--lang LANG zh|en (default: auto)
813980
--path MODE auto|add|skip (default: auto)
814981
--autostart MODE auto|add|skip (default: auto)
982+
--no-verify 跳过 Release 下载的 sha256 校验(不推荐) / Skip sha256 verification (not recommended)
815983
--non-interactive 非交互模式(尽量使用默认值) / Non-interactive (use defaults)
816984
817985
示例 / Examples:
@@ -941,19 +1109,29 @@ fi
9411109
INSTALL_DIR="$(expand_user_path "${INSTALL_DIR}")"
9421110
mkdir -p "${INSTALL_DIR}"
9431111

944-
need go
945-
9461112
say "安装目录:${INSTALL_DIR}" "Install dir: ${INSTALL_DIR}"
9471113

948-
if in_repo; then
1114+
release_repo="${VG_INSTALL_REPO:-inkdust2021/VibeGuard}"
1115+
if ! in_repo; then
1116+
# 非源码目录:优先从 GitHub Release 下载预编译二进制(不需要 Go)
1117+
if ! install_vibeguard_from_release "${INSTALL_DIR}" "${release_repo}" "${INSTALL_VERSION}" "${VERIFY_RELEASE}"; then
1118+
say "Release 安装失败:将回退到 go install(需要 Go)" "Release install failed: falling back to go install (requires Go)"
1119+
need go
1120+
GOBIN="${INSTALL_DIR}" go install github.com/inkdust2021/vibeguard/cmd/vibeguard@latest
1121+
fi
1122+
else
1123+
# 源码目录:默认本地构建(更适合开发/调试)
1124+
need go
9491125
say "检测到仓库源码:从源码构建并安装" "Repo detected: build from source"
950-
tmp="$(mktemp -d)"
1126+
tmp="$(mktemp -d -t vibeguard-build.XXXXXX 2>/dev/null || mktemp -d "/tmp/vibeguard-build.XXXXXX")"
9511127
trap 'rm -rf "$tmp"' EXIT
9521128
go build -o "${tmp}/vibeguard" ./cmd/vibeguard
953-
install -m 0755 "${tmp}/vibeguard" "${INSTALL_DIR}/vibeguard"
954-
else
955-
say "未检测到源码:通过 go install 安装" "Repo not found: installing via go install"
956-
GOBIN="${INSTALL_DIR}" go install github.com/inkdust2021/vibeguard/cmd/vibeguard@latest
1129+
if have install; then
1130+
install -m 0755 "${tmp}/vibeguard" "${INSTALL_DIR}/vibeguard"
1131+
else
1132+
cp -f "${tmp}/vibeguard" "${INSTALL_DIR}/vibeguard"
1133+
chmod 0755 "${INSTALL_DIR}/vibeguard" >/dev/null 2>&1 || true
1134+
fi
9571135
fi
9581136

9591137
VG="${INSTALL_DIR}/vibeguard"

0 commit comments

Comments
 (0)