Compare commits
6
Commits
92d89717c5
...
v0.0.1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b1ea89ba3d | ||
|
|
9b0f2785cf | ||
|
|
ccc858bfdd | ||
|
|
2be5d4d25b | ||
|
|
95cac4688d | ||
|
|
ad4a87fc9f |
@@ -0,0 +1,109 @@
|
||||
# 发版工作流:推送 v* 标签 → 构建前端并嵌入 → 交叉编译多平台二进制
|
||||
# → 生成发布说明 → 通过 Gitea API 创建 Release 并上传产物。
|
||||
#
|
||||
# 发版操作:
|
||||
# git tag -a v0.0.1 -m "v0.0.1"
|
||||
# git push origin v0.0.1
|
||||
#
|
||||
# 实现说明:刻意不使用任何 JS 类 action(checkout/setup-*/release-*)——
|
||||
# 自托管 runner 常把实例地址注册成 localhost,job 容器内不可达,
|
||||
# 且默认容器镜像可能没有 node。此处全程纯 run 步骤 + 公网域名访问实例,
|
||||
# 容器固定 node:24-bookworm(自带 node 与 git,npm 构建前端所需)。
|
||||
name: Release
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- 'v*'
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
env:
|
||||
SITE: https://git.airnan.cn
|
||||
REPO: wangairnan/pure-note
|
||||
|
||||
jobs:
|
||||
release:
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: node:24-bookworm
|
||||
env:
|
||||
# 这台 runner 只保证 GITHUB_* 兼容层(GITEA_REF_NAME 等别名不可靠),
|
||||
# 一律经表达式显式注入,不直接读 GITEA_* 环境变量
|
||||
TAG: ${{ github.ref_name }}
|
||||
TOKEN: ${{ secrets.GITHUB_TOKEN || secrets.GITEA_TOKEN || secrets.FORGEJO_TOKEN }}
|
||||
steps:
|
||||
# 完整历史:供 git log 生成上一个 tag 以来的变更日志
|
||||
- name: 检出代码
|
||||
run: |
|
||||
git clone "$SITE/$REPO.git" .
|
||||
git checkout --detach "$TAG"
|
||||
git log --oneline -1
|
||||
|
||||
- name: 安装 Go(版本取自 go.mod)
|
||||
run: |
|
||||
set -euo pipefail
|
||||
GOVER=$(awk '$1 == "go" {print $2}' go.mod)
|
||||
echo "==> 安装 Go $GOVER"
|
||||
# go.dev 在部分网络不可达,回退官方中国镜像
|
||||
curl -fsSL "https://go.dev/dl/go${GOVER}.linux-amd64.tar.gz" -o /tmp/go.tgz \
|
||||
|| curl -fsSL "https://golang.google.cn/dl/go${GOVER}.linux-amd64.tar.gz" -o /tmp/go.tgz
|
||||
tar -C /usr/local -xzf /tmp/go.tgz
|
||||
/usr/local/go/bin/go version
|
||||
|
||||
- name: 构建前端并嵌入(web/dist → internal/webui/dist)
|
||||
run: make web sync-assets || (npm config set registry https://registry.npmmirror.com && make web sync-assets)
|
||||
|
||||
- name: 交叉编译发布产物
|
||||
run: |
|
||||
set -euo pipefail
|
||||
export PATH=/usr/local/go/bin:$PATH
|
||||
# 模块代理双层回退:官方代理不可达时走 goproxy.cn
|
||||
export GOPROXY=https://proxy.golang.org,https://goproxy.cn,direct
|
||||
scripts/build-release.sh "$TAG"
|
||||
|
||||
# 首个 tag 无上一版本,变更日志段自动省略
|
||||
- name: 生成发布说明
|
||||
run: |
|
||||
set -euo pipefail
|
||||
prev=$(git describe --tags --abbrev=0 "HEAD^" 2>/dev/null || true)
|
||||
short=$(git rev-parse --short HEAD)
|
||||
{
|
||||
echo "## pn ${TAG}"
|
||||
echo
|
||||
echo "- commit: \`$short\`"
|
||||
echo "- 构建时间: $(date -u '+%Y-%m-%dT%H:%M:%SZ')"
|
||||
if [ -n "$prev" ]; then
|
||||
echo
|
||||
echo "### 自 ${prev} 以来的变更"
|
||||
echo
|
||||
git log --oneline --no-decorate "${prev}..HEAD" | sed 's/^/- /'
|
||||
fi
|
||||
} > release-notes.md
|
||||
cat release-notes.md
|
||||
|
||||
# 重跑幂等:release 已存在时更新说明、清旧附件后重传
|
||||
- name: 创建 Release 并上传产物
|
||||
run: |
|
||||
set -euo pipefail
|
||||
API="$SITE/api/v1/repos/$REPO"
|
||||
AUTH="Authorization: token ${TOKEN}"
|
||||
REQ=$(node -e 'const fs=require("fs");process.stdout.write(JSON.stringify({tag_name:process.env.TAG,name:"pn "+process.env.TAG,body:fs.readFileSync("release-notes.md","utf8")}))')
|
||||
# 同 tag release 已存在(如失败重跑)时回退为查询
|
||||
REL=$(curl -fsS -X POST "$API/releases" -H "$AUTH" -H 'Content-Type: application/json' -d "$REQ") \
|
||||
|| REL=$(curl -fsS "$API/releases/tags/${TAG}" -H "$AUTH")
|
||||
RID=$(REL="$REL" node -e 'process.stdout.write(String(JSON.parse(process.env.REL).id))')
|
||||
echo "==> release id=$RID"
|
||||
# 发布说明以本次构建为准(回退路径下 POST 已冲突,须补写)
|
||||
curl -fsS -X PATCH "$API/releases/$RID" -H "$AUTH" -H 'Content-Type: application/json' -d "$REQ" >/dev/null
|
||||
# 清除旧附件,避免重跑产生同名副本
|
||||
ASSETS=$(curl -fsS "$API/releases/$RID/assets" -H "$AUTH")
|
||||
ASSETS="$ASSETS" node -e 'JSON.parse(process.env.ASSETS).forEach(a=>console.log(a.id))' | while read -r aid; do
|
||||
curl -fsS -X DELETE "$API/releases/$RID/assets/$aid" -H "$AUTH" >/dev/null
|
||||
done
|
||||
for f in dist/*; do
|
||||
echo "==> 上传 $(basename "$f")"
|
||||
curl -fsS -X POST "$API/releases/$RID/assets?name=$(basename "$f")" -H "$AUTH" -F "attachment=@$f" >/dev/null
|
||||
done
|
||||
echo "==> 完成:$SITE/$REPO/releases/tag/${TAG}"
|
||||
@@ -13,5 +13,8 @@ internal/webui/dist/*
|
||||
/pn
|
||||
/pn-linux-*
|
||||
|
||||
# 发布产物(make dist / CI 发版构建输出)
|
||||
/dist/
|
||||
|
||||
# 系统文件
|
||||
.DS_Store
|
||||
@@ -5,17 +5,21 @@
|
||||
# make sync-assets 拷贝 web/dist → internal/webui/dist(go:embed 约束,§8.3-1)
|
||||
# make build 全量构建(前端 + 单二进制 pn)
|
||||
# make linux 交叉编译 linux/amd64
|
||||
# make dist 全平台发布产物 → dist/(VERSION ?= git describe,与 CI 发版共用脚本)
|
||||
# make test Go 测试 + 前端测试
|
||||
# make smoke 真实构建冒烟测试(§8.3-6)
|
||||
# make dev 双进程热重载(air + vite dev)
|
||||
# make vulncheck govulncheck
|
||||
#
|
||||
# 发版:git tag -a v0.0.1 -m "v0.0.1" && git push origin v0.0.1
|
||||
# (推送 v* 标签触发 .gitea/workflows/release.yml 自动构建并创建 Release)
|
||||
|
||||
VERSION ?= $(shell git describe --tags --always 2>/dev/null || echo dev)
|
||||
COMMIT ?= $(shell git rev-parse --short HEAD 2>/dev/null || echo none)
|
||||
DATE ?= $(shell date -u +%Y-%m-%dT%H:%M:%SZ)
|
||||
LDFLAGS := -s -w -X main.version=$(VERSION) -X main.commit=$(COMMIT) -X main.buildDate=$(DATE)
|
||||
|
||||
.PHONY: web sync-assets build linux test smoke dev vulncheck clean
|
||||
.PHONY: web sync-assets build linux dist test smoke dev vulncheck clean
|
||||
|
||||
web:
|
||||
cd web && npm ci && npm run build
|
||||
@@ -33,6 +37,10 @@ linux: web sync-assets
|
||||
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -trimpath -ldflags="$(LDFLAGS)" \
|
||||
-o pn-linux-amd64 ./cmd/pn
|
||||
|
||||
# 全平台发布产物(版本注入逻辑与 CI 发版共用 scripts/build-release.sh)
|
||||
dist: web sync-assets
|
||||
scripts/build-release.sh "$(VERSION)"
|
||||
|
||||
test:
|
||||
go vet ./...
|
||||
go test ./...
|
||||
@@ -51,3 +59,4 @@ vulncheck:
|
||||
|
||||
clean:
|
||||
rm -f pn pn-linux-amd64
|
||||
rm -rf dist
|
||||
|
||||
@@ -78,6 +78,22 @@ sudo systemctl enable --now pn pn-maint.timer
|
||||
|
||||
**恢复 SOP**:停服 → 删除 `data/pn.db-wal` 与 `-shm` → 以备份文件替换 `pn.db` → 起服。
|
||||
|
||||
## 版本与发版
|
||||
|
||||
版本号以 git tag 为唯一来源(语义化版本,从 `v0.0.1` 开始),构建时经 ldflags 注入,
|
||||
`./pn version` 可查看:
|
||||
|
||||
```bash
|
||||
git tag -a v0.0.1 -m "v0.0.1"
|
||||
git push origin v0.0.1 # 推送 v* 标签即触发自动发版
|
||||
```
|
||||
|
||||
推送 `v*` 标签后,Gitea Actions([.gitea/workflows/release.yml](.gitea/workflows/release.yml))
|
||||
自动构建前端并嵌入,交叉编译 linux/darwin(amd64 + arm64)共 4 个产物,
|
||||
连同 SHA256SUMS 与上一版本以来的变更日志一起发布到仓库的 Release 页面。
|
||||
|
||||
本地验证发布产物:`make dist`(版本缺省 `git describe --tags --always`,输出到 `dist/`)。
|
||||
|
||||
## 架构
|
||||
|
||||
```
|
||||
|
||||
Executable
+52
@@ -0,0 +1,52 @@
|
||||
#!/usr/bin/env bash
|
||||
# 发布产物构建:交叉编译全部目标平台 → dist/,打包并生成 SHA256SUMS。
|
||||
# 本地 `make dist` 与 Gitea Actions 发版工作流共用本脚本,保证产物一致。
|
||||
#
|
||||
# 用法: scripts/build-release.sh [版本号]
|
||||
# 版本号缺省取 `git describe --tags --always`(无 tag 时回退 dev)。
|
||||
# 前置条件:internal/webui/dist 已就绪(make web sync-assets)。
|
||||
set -euo pipefail
|
||||
|
||||
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
|
||||
cd "$ROOT"
|
||||
|
||||
VERSION="${1:-$(git describe --tags --always 2>/dev/null || echo dev)}"
|
||||
COMMIT="$(git rev-parse --short HEAD 2>/dev/null || echo none)"
|
||||
DATE="$(date -u +%Y-%m-%dT%H:%M:%SZ)"
|
||||
LDFLAGS="-s -w -X main.version=$VERSION -X main.commit=$COMMIT -X main.buildDate=$DATE"
|
||||
|
||||
# 纯静态(CGO_ENABLED=0,见 Makefile),单机即可交叉编译全部目标。
|
||||
# 不含 windows:internal/store 对 syscall.Umask 等 Unix API 有硬依赖(备份权限加固)。
|
||||
TARGETS=(
|
||||
linux/amd64
|
||||
linux/arm64
|
||||
darwin/amd64
|
||||
darwin/arm64
|
||||
)
|
||||
|
||||
rm -rf dist
|
||||
mkdir -p dist
|
||||
|
||||
for t in "${TARGETS[@]}"; do
|
||||
os="${t%/*}" arch="${t#*/}"
|
||||
name="pn-${VERSION}-${os}-${arch}"
|
||||
echo "==> 构建 $name"
|
||||
CGO_ENABLED=0 GOOS="$os" GOARCH="$arch" \
|
||||
go build -trimpath -ldflags="$LDFLAGS" -o "dist/$name" ./cmd/pn
|
||||
# tar.gz 保留可执行位
|
||||
(cd dist && tar czf "$name.tar.gz" "$name" && rm "$name")
|
||||
done
|
||||
|
||||
# 生成校验和(Linux 为 sha256sum,macOS 回退 shasum)
|
||||
echo "==> 生成 SHA256SUMS"
|
||||
(
|
||||
cd dist
|
||||
if command -v sha256sum >/dev/null 2>&1; then
|
||||
sha256sum -- ./* > SHA256SUMS
|
||||
else
|
||||
shasum -a 256 -- ./* > SHA256SUMS
|
||||
fi
|
||||
)
|
||||
|
||||
echo "==> 完成:dist/"
|
||||
ls -lh dist/
|
||||
Reference in New Issue
Block a user