Skip to content

Commit 5af22aa

Browse files
VincentZyuwin11台式机VincentZyuwin11台式机
authored andcommitted
ci: refactor flags & add scoop publish job [build publish] - bump to 0.1.5-beta.2
1 parent 16d8285 commit 5af22aa

4 files changed

Lines changed: 307 additions & 15 deletions

File tree

.github/workflows/build.md

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
# Build & Release Workflow
2+
3+
> **[📖 中文文档](build.zh-cn.md)**
4+
5+
## 📋 Overview
6+
7+
The CI/CD pipeline is driven entirely by **commit message keywords**. Push to `main` with the right keyword and GitHub Actions takes care of the rest.
8+
9+
## 🔑 Keywords
10+
11+
| Keyword in commit message | Build (6 platforms) | GitHub Release | Scoop Bucket |
12+
|---------------------------|:---:|:---:|:---:|
13+
| *(none)* ||||
14+
| `build action` ||||
15+
| `build release` ||||
16+
| `publish from release` ||||
17+
| `build publish` ||||
18+
19+
> **Note:** `publish from release` fetches binaries from an existing Release without rebuilding. `build publish` does the full pipeline.
20+
21+
> **Note:** Pull Requests always trigger a build (no release or publish).
22+
23+
## 🚀 Usage Examples
24+
25+
```bash
26+
# Just build, verify compilation across all platforms
27+
git commit --allow-empty -m "ci: test cross-compile (build action)"
28+
29+
# Build + create GitHub Release with artifacts
30+
git commit -m "release: v0.2.0 (build release)"
31+
32+
# Only update Scoop bucket from the latest existing Release (no rebuild)
33+
git commit --allow-empty -m "ci: update scoop (publish from release)"
34+
35+
# Full pipeline: build + release + publish to Scoop
36+
git commit -m "release: v0.2.0 (build publish)"
37+
```
38+
39+
## 🏗️ Build Targets
40+
41+
| Platform | Architecture | Target | Notes |
42+
|----------|:---:|--------|-------|
43+
| Windows | x64 | `x86_64-pc-windows-msvc` | Native MSVC |
44+
| Windows | ARM64 | `aarch64-pc-windows-msvc` | Cross-compiled on x64 runner |
45+
| Linux | x64 | `x86_64-unknown-linux-musl` | Static linking (musl), portable |
46+
| Linux | ARM64 | `aarch64-unknown-linux-gnu` | Built on ubuntu-22.04 for lower GLIBC |
47+
| macOS | x64 | `x86_64-apple-darwin` | Built on Apple Silicon runner |
48+
| macOS | ARM64 | `aarch64-apple-darwin` | Native Apple Silicon |
49+
50+
## 📦 Pipeline Stages
51+
52+
```
53+
check ──→ build ──→ release ──→ publish-scoop
54+
│ │ │ │
55+
│ │ │ └─ Download binaries from Release
56+
│ │ │ Generate winload.json
57+
│ │ │ Push to scoop-bucket repo
58+
│ │ │
59+
│ │ └─ Download artifacts
60+
│ │ Delete old release/tag
61+
│ │ Generate release notes
62+
│ │ Create GitHub Release
63+
│ │
64+
│ └─ Compile for 6 platform targets
65+
│ Upload build artifacts
66+
67+
└─ Parse commit message keywords
68+
Extract version from Cargo.toml
69+
```
70+
71+
## 🍺 Scoop Publish
72+
73+
The `publish` keyword triggers an update to the [scoop-bucket](https://github.com/VincentZyuApps/scoop-bucket) repository:
74+
75+
1. Downloads Windows x64 and ARM64 binaries from the latest GitHub Release
76+
2. Computes SHA256 hashes
77+
3. Generates `winload.json` manifest (with both `64bit` and `arm64` architecture support)
78+
4. Pushes to `VincentZyuApps/scoop-bucket`
79+
80+
### Prerequisite
81+
82+
A repository secret `SCOOP_BUCKET_TOKEN` must be set in **Settings → Secrets → Actions**, containing a GitHub PAT with `repo` scope.
83+
84+
## 📌 Version
85+
86+
The version is automatically extracted from `rust/Cargo.toml` and used for:
87+
- Release tag name (e.g. `v0.1.5`)
88+
- Artifact filenames (e.g. `winload-windows-x86_64-v0.1.5.exe`)
89+
- Scoop manifest version field

.github/workflows/build.yml

Lines changed: 128 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -41,26 +41,35 @@ jobs:
4141
exit 0
4242
fi
4343
44-
# "build publish" = 完整发布流程
44+
# 初始化标志
45+
BUILD=false
46+
RELEASE=false
47+
PUBLISH=false
48+
49+
# "build publish" = 构建 + Release + 发布到包管理器 (全套)
4550
if echo "$MSG" | grep -qi "build publish"; then
46-
echo "should_build=true" >> "$GITHUB_OUTPUT"
47-
echo "should_release=true" >> "$GITHUB_OUTPUT"
48-
echo "should_publish=true" >> "$GITHUB_OUTPUT"
51+
BUILD=true
52+
RELEASE=true
53+
PUBLISH=true
4954
# "build release" = 构建 + GitHub Release
5055
elif echo "$MSG" | grep -qi "build release"; then
51-
echo "should_build=true" >> "$GITHUB_OUTPUT"
52-
echo "should_release=true" >> "$GITHUB_OUTPUT"
53-
echo "should_publish=false" >> "$GITHUB_OUTPUT"
56+
BUILD=true
57+
RELEASE=true
5458
# "build action" = 仅构建
5559
elif echo "$MSG" | grep -qi "build action"; then
56-
echo "should_build=true" >> "$GITHUB_OUTPUT"
57-
echo "should_release=false" >> "$GITHUB_OUTPUT"
58-
echo "should_publish=false" >> "$GITHUB_OUTPUT"
59-
else
60-
echo "should_build=false" >> "$GITHUB_OUTPUT"
61-
echo "should_release=false" >> "$GITHUB_OUTPUT"
62-
echo "should_publish=false" >> "$GITHUB_OUTPUT"
60+
BUILD=true
6361
fi
62+
63+
# "publish from release" = 从已有 Release 发布到包管理器 (不构建)
64+
if echo "$MSG" | grep -qi "publish from release"; then
65+
PUBLISH=true
66+
fi
67+
68+
echo "should_build=$BUILD" >> "$GITHUB_OUTPUT"
69+
echo "should_release=$RELEASE" >> "$GITHUB_OUTPUT"
70+
echo "should_publish=$PUBLISH" >> "$GITHUB_OUTPUT"
71+
72+
echo "📋 Flags: build=$BUILD release=$RELEASE publish=$PUBLISH"
6473
6574
# ── 多平台构建 ───────────────────────────────────────────
6675
build:
@@ -297,3 +306,108 @@ jobs:
297306
--notes-file release_notes.md \
298307
--latest \
299308
winload-*-${VERSION}*
309+
310+
# ── 更新 Scoop Bucket ─────────────────────────────────
311+
# 触发方式:
312+
# - "publish from release" → 从已有 Release 拉取二进制,仅更新 Scoop
313+
# - "build publish" → 构建 + Release + 更新 Scoop(全套)
314+
publish-scoop:
315+
name: Update Scoop Bucket
316+
needs: [check, release]
317+
# always() 让此 job 即使 release 被跳过也能运行
318+
if: always() && needs.check.outputs.should_publish == 'true' && (needs.release.result == 'success' || needs.release.result == 'skipped')
319+
runs-on: ubuntu-latest
320+
steps:
321+
- name: Fetch latest release info
322+
env:
323+
GH_TOKEN: ${{ github.token }}
324+
run: |
325+
VERSION="${{ needs.check.outputs.version }}"
326+
REPO="${{ github.repository }}"
327+
BASE_URL="https://github.com/${REPO}/releases/download/${VERSION}"
328+
329+
echo "📦 Target version: ${VERSION}"
330+
echo "📥 Downloading Windows binaries from release..."
331+
332+
# 下载 Windows x64
333+
curl -fSL -o winload-windows-x86_64.exe \
334+
"${BASE_URL}/winload-windows-x86_64-${VERSION}.exe" \
335+
|| { echo "❌ Failed to download x64 binary"; exit 1; }
336+
337+
# 下载 Windows ARM64
338+
curl -fSL -o winload-windows-aarch64.exe \
339+
"${BASE_URL}/winload-windows-aarch64-${VERSION}.exe" \
340+
|| { echo "❌ Failed to download arm64 binary"; exit 1; }
341+
342+
echo "✅ Downloaded:"
343+
ls -lh winload-windows-*.exe
344+
345+
- name: Generate Scoop manifest
346+
run: |
347+
VERSION="${{ needs.check.outputs.version }}"
348+
SCOOP_VERSION="${VERSION#v}"
349+
REPO="${{ github.repository }}"
350+
BASE_URL="https://github.com/${REPO}/releases/download/${VERSION}"
351+
352+
# 计算 sha256
353+
HASH_X64=$(sha256sum winload-windows-x86_64.exe | awk '{print $1}')
354+
HASH_ARM64=$(sha256sum winload-windows-aarch64.exe | awk '{print $1}')
355+
356+
echo "📦 Version: $SCOOP_VERSION"
357+
echo "🔑 x64 hash: $HASH_X64"
358+
echo "🔑 arm64 hash: $HASH_ARM64"
359+
360+
cat > winload.json << EOF
361+
{
362+
"version": "${SCOOP_VERSION}",
363+
"description": "Network Load Monitor - nload for Windows/Linux/macOS",
364+
"homepage": "https://github.com/${REPO}",
365+
"license": "MIT",
366+
"architecture": {
367+
"64bit": {
368+
"url": "${BASE_URL}/winload-windows-x86_64-${VERSION}.exe",
369+
"hash": "${HASH_X64}",
370+
"bin": [["winload-windows-x86_64-${VERSION}.exe", "winload"]]
371+
},
372+
"arm64": {
373+
"url": "${BASE_URL}/winload-windows-aarch64-${VERSION}.exe",
374+
"hash": "${HASH_ARM64}",
375+
"bin": [["winload-windows-aarch64-${VERSION}.exe", "winload"]]
376+
}
377+
},
378+
"checkver": {
379+
"github": "https://github.com/${REPO}"
380+
},
381+
"autoupdate": {
382+
"architecture": {
383+
"64bit": {
384+
"url": "https://github.com/${REPO}/releases/download/v\$version/winload-windows-x86_64-v\$version.exe"
385+
},
386+
"arm64": {
387+
"url": "https://github.com/${REPO}/releases/download/v\$version/winload-windows-aarch64-v\$version.exe"
388+
}
389+
}
390+
}
391+
}
392+
EOF
393+
394+
echo "📝 Generated winload.json:"
395+
cat winload.json
396+
397+
- name: Push to scoop-bucket repo
398+
env:
399+
SCOOP_TOKEN: ${{ secrets.SCOOP_BUCKET_TOKEN }}
400+
run: |
401+
VERSION="${{ needs.check.outputs.version }}"
402+
403+
git clone https://x-access-token:${SCOOP_TOKEN}@github.com/VincentZyuApps/scoop-bucket.git scoop-repo
404+
cp winload.json scoop-repo/bucket/winload.json
405+
406+
cd scoop-repo
407+
git config user.name "github-actions[bot]"
408+
git config user.email "github-actions[bot]@users.noreply.github.com"
409+
git add bucket/winload.json
410+
git commit -m "🍺 Update winload to ${VERSION}" || echo "No changes to commit"
411+
git push
412+
413+
echo "✅ Scoop bucket updated!"

.github/workflows/build.zh-cn.md

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
# 构建与发布工作流
2+
3+
> **[📖 English](build.md)**
4+
5+
## 📋 概述
6+
7+
CI/CD 流水线完全由 **commit 信息中的关键词** 驱动。推送到 `main` 分支时,只需在 commit message 中包含对应关键词,GitHub Actions 会自动完成后续工作。
8+
9+
## 🔑 关键词
10+
11+
| Commit 信息中的关键词 | 构建(6 平台) | GitHub Release | Scoop Bucket |
12+
|----------------------|:---:|:---:|:---:|
13+
| *(无关键词)* ||||
14+
| `build action` ||||
15+
| `build release` ||||
16+
| `publish from release` ||||
17+
| `build publish` ||||
18+
19+
> **说明:** `publish from release` 从已有的 Release 拉取二进制发布,不会重新构建。`build publish` 则是完整流水线。
20+
21+
> **说明:** Pull Request 始终会触发构建(不会发布或推送包管理器)。
22+
23+
## 🚀 用法示例
24+
25+
```bash
26+
# 仅构建,验证所有平台的编译
27+
git commit --allow-empty -m "ci: test cross-compile (build action)"
28+
29+
# 构建 + 创建 GitHub Release
30+
git commit -m "release: v0.2.0 (build release)"
31+
32+
# 仅更新 Scoop bucket(从已有的最新 Release 拉取二进制,不重新构建)
33+
git commit --allow-empty -m "ci: update scoop (publish from release)"
34+
35+
# 完整流水线:构建 + 发布 Release + 推送 Scoop
36+
git commit -m "release: v0.2.0 (build publish)"
37+
```
38+
39+
## 🏗️ 构建目标
40+
41+
| 平台 | 架构 | Target | 说明 |
42+
|------|:---:|--------|------|
43+
| Windows | x64 | `x86_64-pc-windows-msvc` | 原生 MSVC 编译 |
44+
| Windows | ARM64 | `aarch64-pc-windows-msvc` | 在 x64 runner 上交叉编译 |
45+
| Linux | x64 | `x86_64-unknown-linux-musl` | musl 静态链接,可移植 |
46+
| Linux | ARM64 | `aarch64-unknown-linux-gnu` | 在 ubuntu-22.04 上编译,降低 GLIBC 要求 |
47+
| macOS | x64 | `x86_64-apple-darwin` | 在 Apple Silicon runner 上编译 |
48+
| macOS | ARM64 | `aarch64-apple-darwin` | 原生 Apple Silicon |
49+
50+
## 📦 流水线阶段
51+
52+
```
53+
check ──→ build ──→ release ──→ publish-scoop
54+
│ │ │ │
55+
│ │ │ └─ 从 Release 下载二进制
56+
│ │ │ 生成 winload.json
57+
│ │ │ 推送到 scoop-bucket 仓库
58+
│ │ │
59+
│ │ └─ 下载构建产物
60+
│ │ 删除旧的 release/tag
61+
│ │ 生成 release notes
62+
│ │ 创建 GitHub Release
63+
│ │
64+
│ └─ 编译 6 个平台目标
65+
│ 上传构建产物
66+
67+
└─ 解析 commit 信息关键词
68+
从 Cargo.toml 提取版本号
69+
```
70+
71+
## 🍺 Scoop 发布
72+
73+
`publish` 关键词会触发 [scoop-bucket](https://github.com/VincentZyuApps/scoop-bucket) 仓库的更新:
74+
75+
1. 从最新的 GitHub Release 下载 Windows x64 和 ARM64 二进制文件
76+
2. 计算 SHA256 哈希值
77+
3. 生成 `winload.json` 清单文件(包含 `64bit``arm64` 两种架构)
78+
4. 推送到 `VincentZyuApps/scoop-bucket` 仓库
79+
80+
### 前置条件
81+
82+
需要在仓库的 **Settings → Secrets → Actions** 中设置 `SCOOP_BUCKET_TOKEN` 密钥,值为一个拥有 `repo` 权限的 GitHub Personal Access Token。
83+
84+
## 📌 版本号
85+
86+
版本号自动从 `rust/Cargo.toml` 中提取,用于:
87+
- Release 标签名(如 `v0.1.5`
88+
- 产物文件名(如 `winload-windows-x86_64-v0.1.5.exe`
89+
- Scoop 清单文件中的版本字段

rust/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "winload"
3-
version = "0.1.5-beta.1"
3+
version = "0.1.5-beta.2"
44
edition = "2021"
55
description = "Network Load Monitor — nload-like TUI tool for Windows/Linux/macOS"
66
license = "MIT"

0 commit comments

Comments
 (0)