release

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Freenet Release Skill

Freenet版本发布Skill

Overview

概述

This skill orchestrates a complete Freenet release. It determines the next version, shows what's changed since the last release, confirms with the user, and runs the automated release pipeline.
本Skill可编排完整的Freenet版本发布流程。它会确定下一个版本号、展示自上次发布以来的变更内容、与用户确认后运行自动化发布流水线。

Arguments

参数说明

  • If an argument is provided (e.g.,
    /release 0.1.133
    ), use that as the target version
  • If no argument is provided, auto-detect the next patch version
  • 若提供了参数(例如
    /release 0.1.133
    ),则将该参数作为目标版本号
  • 若未提供参数,则自动检测下一个补丁版本号

Step 1: Determine Current State

步骤1:确定当前状态

Run these commands to gather release context:
bash
undefined
运行以下命令收集发布相关信息:
bash
undefined

Get current version from Cargo.toml

从Cargo.toml获取当前版本

grep "^version" crates/core/Cargo.toml | cut -d'"' -f2
grep "^version" crates/core/Cargo.toml | cut -d'"' -f2

Get the last release tag

获取上一个发布标签

git describe --tags --abbrev=0
git describe --tags --abbrev=0

Get commits since last release

获取自上次发布以来的提交记录

git log --oneline $(git describe --tags --abbrev=0)..HEAD

**Auto-version logic:** If no version argument was provided, increment the patch version of the current version (e.g., `0.1.132` -> `0.1.133`).
git log --oneline $(git describe --tags --abbrev=0)..HEAD

**自动版本号逻辑:** 若未提供版本参数,则将当前版本的补丁号递增(例如`0.1.132` -> `0.1.133`)。

Step 2: Show Changelog and Confirm

步骤2:展示更新日志并确认

Present the user with:
  1. Current version and target version
  2. Commits since last release (categorized by conventional commit type)
  3. fdev version that will be auto-incremented
Then ask the user to confirm before proceeding.
向用户展示以下内容:
  1. 当前版本号目标版本号
  2. 自上次发布以来的提交记录(按规范提交类型分类)
  3. 将自动递增的fdev版本号
然后在继续执行前请求用户确认。

Step 3: Pre-flight Checks

步骤3:预发布检查

Before running the release script, verify:
bash
undefined
在运行发布脚本前,需验证以下内容:
bash
undefined

Must be on main branch (or a release worktree)

必须处于main分支(或发布工作树)

git branch --show-current
git branch --show-current

Must have clean working directory

工作目录必须干净无变更

git status --porcelain # Should be empty
git status --porcelain # 输出应为空

Must be up to date with origin

必须与远程仓库origin保持同步

git fetch origin main git rev-parse HEAD # Compare with: git rev-parse origin/main

If any check fails, inform the user and stop.
git fetch origin main git rev-parse HEAD # 与以下命令结果对比: git rev-parse origin/main

若任何一项验证失败,需告知用户并终止流程。

Optional: Create a Release Worktree

可选:创建发布工作树

To avoid disrupting the main worktree:
bash
cd ~/code/freenet/freenet-core/main  # or wherever main worktree is
git worktree add -b release-work ../release-X.Y.Z
cd ../release-X.Y.Z
Clean up after release:
bash
git worktree remove ../release-X.Y.Z
git branch -d release-work
为避免干扰主工作树,可执行以下操作:
bash
cd ~/code/freenet/freenet-core/main  # 或主工作树所在的其他路径
git worktree add -b release-work ../release-X.Y.Z
cd ../release-X.Y.Z
发布完成后清理:
bash
git worktree remove ../release-X.Y.Z
git branch -d release-work

Step 4: Run the Release

步骤4:执行发布

Execute the release script:
bash
./scripts/release.sh --version <VERSION> [--skip-tests] [--deploy-local]
The script handles the entire pipeline:
  1. Version bump - Updates
    crates/core/Cargo.toml
    and
    crates/fdev/Cargo.toml
  2. Release PR - Creates a branch, commits, pushes, opens PR with auto-merge
  3. Wait for CI - Monitors GitHub CI on the release PR (up to 30 min)
  4. Publish crates - Publishes
    freenet
    then
    fdev
    to crates.io
  5. GitHub Release - Creates tag, generates release notes, creates release
  6. Cross-compile - Triggered automatically by the tag push
  7. Wait for binaries - Waits for cross-compile to attach binaries to the release
  8. Announcements - Matrix and River notifications (if tools available)
执行发布脚本:
bash
./scripts/release.sh --version <VERSION> [--skip-tests] [--deploy-local]
该脚本会处理完整的发布流水线:
  1. 版本号更新 - 更新
    crates/core/Cargo.toml
    crates/fdev/Cargo.toml
    中的版本号
  2. 创建发布PR - 创建分支、提交变更、推送到远程仓库并开启自动合并的PR
  3. 等待CI完成 - 监控发布PR的GitHub CI流程(最长等待30分钟)
  4. 发布到crates.io - 先将
    freenet
    发布到crates.io,再发布
    fdev
  5. 创建GitHub Release - 创建版本标签、生成发布说明并创建Release
  6. 交叉编译 - 推送标签后自动触发交叉编译流程
  7. 等待二进制文件生成 - 等待交叉编译完成并将二进制文件附加到Release中
  8. 发布通知 - 发送Matrix和River通知(若相关工具可用)

Important Options

重要选项

  • --skip-tests
    - Skip local pre-release tests (CI still runs on the PR)
  • --dry-run
    - Show what would be done without executing
  • --deploy-local
    - Deploy to local gateway after release
  • --deploy-remote
    - Deploy to remote gateways after release
  • --skip-tests
    - 跳过本地预发布测试(PR上的CI仍会运行)
  • --dry-run
    - 展示将要执行的操作但不实际执行
  • --deploy-local
    - 发布完成后部署到本地网关
  • --deploy-remote
    - 发布完成后部署到远程网关

Resumability

断点续传

The release script is resumable. If it fails partway through, re-running with the same
--version
will auto-detect completed steps and skip them. State is saved to
/tmp/release-<VERSION>.state
.
You can also resume explicitly:
./scripts/release.sh --resume /tmp/release-<VERSION>.state
发布脚本支持断点续传。若脚本在执行中途失败,使用相同的
--version
参数重新运行时,会自动检测已完成的步骤并跳过。状态信息会保存到
/tmp/release-<VERSION>.state
你也可以显式指定恢复:
./scripts/release.sh --resume /tmp/release-<VERSION>.state

Step 5: Handle Common Issues

步骤5:处理常见问题

PR title / Conventional Commits check fails: Release PRs must use "build:" prefix (not "chore:"). The commit-msg hook only allows: feat, fix, docs, style, refactor, perf, test, build, ci.
bash
gh api repos/freenet/freenet-core/pulls/XXXX --method PATCH -f title="build: release X.Y.Z"
Auto-merge not triggering:
  • GitHub auto-merge can take 5-10 minutes after checks pass
  • The script waits up to 30 minutes (showing progress every 30s)
  • You can manually merge the PR — the script detects manual merges and continues
Test failures: Check CI logs. Either fix the issue or inform the user and ask how to proceed.
PR标题/规范提交检查失败: 发布PR的标题必须使用“build:”前缀(不能用“chore:”)。commit-msg钩子仅允许使用以下前缀:feat、fix、docs、style、refactor、perf、test、build、ci。
bash
gh api repos/freenet/freenet-core/pulls/XXXX --method PATCH -f title="build: release X.Y.Z"
自动合并未触发:
  • GitHub自动合并在检查通过后可能需要5-10分钟
  • 脚本会等待最多30分钟(每30秒展示一次进度)
  • 你可以手动合并PR — 脚本会检测到手动合并并继续执行后续流程
测试失败: 检查CI日志。要么修复问题,要么告知用户并询问后续处理方式。

Step 6: Verify Release Artifacts

步骤6:验证发布产物

CRITICAL: Do NOT announce until cross-compile binaries are available. The
Build and Cross-Compile
workflow triggers on tag push and takes ~15-20 min to build binaries for all platforms. Gateway auto-update depends on these binaries.
bash
undefined
重要提示:在交叉编译的二进制文件生成完成前,请勿发布通知。
Build and Cross-Compile
工作流会在推送标签后触发,为所有平台构建二进制文件需要约15-20分钟。网关的自动更新依赖于这些二进制文件。
bash
undefined

Check crates.io publication

检查crates.io上的发布情况

cargo search freenet --limit 1
cargo search freenet --limit 1

Check GitHub release exists

检查GitHub Release是否创建成功

gh release view v<VERSION>
gh release view v<VERSION>

Verify binaries are attached

验证二进制文件是否已附加到Release

gh release view v<VERSION> --json assets --jq '.assets[].name'
gh release view v<VERSION> --json assets --jq '.assets[].name'

Should show: freenet-x86_64-unknown-linux-musl.tar.gz, freenet-aarch64-unknown-linux-musl.tar.gz, etc.

应显示:freenet-x86_64-unknown-linux-musl.tar.gz、freenet-aarch64-unknown-linux-musl.tar.gz等文件

Monitor cross-compile workflow if binaries not yet available

若二进制文件尚未生成,监控交叉编译工作流

gh run list --workflow=cross-compile.yml --limit 3
undefined
gh run list --workflow=cross-compile.yml --limit 3
undefined

Step 7: Announcements

步骤7:发布通知

Only after binaries are confirmed available:
Matrix (#freenet-locutus channel):
bash
undefined
仅在确认二进制文件生成完成后,再执行以下通知操作:
Matrix(#freenet-locutus频道):
bash
undefined

Use matrix-send wrapper if available (handles E2E encryption, retries, timeouts)

若有matrix-send封装工具请使用(支持端到端加密、重试、超时处理)

matrix-send -r '!ygHfYcXtXmivTbOwjX:matrix.org' -m "Freenet vX.Y.Z released - [summary]. https://github.com/freenet/freenet-core/releases/tag/vX.Y.Z"

**River** (Freenet Official room):
```bash
riverctl message send 69Ht4YjZsT884MndR2uWhQYe1wb9b2x77HRq7Dgq7wYE "Freenet vX.Y.Z released - [summary]. https://github.com/freenet/freenet-core/releases/tag/vX.Y.Z"
matrix-send -r '!ygHfYcXtXmivTbOwjX:matrix.org' -m "Freenet vX.Y.Z版本已发布 - [摘要]. https://github.com/freenet/freenet-core/releases/tag/vX.Y.Z"

**River**(Freenet官方房间):
```bash
riverctl message send 69Ht4YjZsT884MndR2uWhQYe1wb9b2x77HRq7Dgq7wYE "Freenet vX.Y.Z版本已发布 - [摘要]. https://github.com/freenet/freenet-core/releases/tag/vX.Y.Z"

Step 8: Post-Release Verification

步骤8:发布后验证

A release is NOT complete until the network is verified healthy.
Wait 10-15 minutes for gateways to auto-update, then verify:
  1. Gateway versions updated — Check that gateways are running the new version
  2. Gateway logs clean — No new errors, warnings, panics, or log spam
  3. Network health — Peers connecting, contracts propagating, subscriptions working
If you have access to gateway machines, check logs directly. If you have access to telemetry, monitor network-wide health. The specific verification steps depend on your access level — see your local environment's release skill for machine-specific commands.
What to look for:
  • Log spam — Same message repeating hundreds of times (can fill disks within hours)
  • Rapid log growth — Normal is ~1MB/hour; much faster indicates a problem
  • New error patterns — Errors not present before the release
  • Connection failures — "connection refused", "timeout", "handshake failed"
  • Resource issues — "out of memory", "no space left", "too many open files"
If critical issues found: Roll back immediately, create GitHub issue, announce rollback.
只有在确认网络状态健康后,发布流程才算完成。
等待10-15分钟让网关完成自动更新,然后验证以下内容:
  1. 网关版本已更新 — 确认网关正在运行新版本
  2. 网关日志无异常 — 无新的错误、警告、崩溃或日志刷屏情况
  3. 网络状态健康 — 节点可正常连接、合约可正常传播、订阅功能正常
若你有权限访问网关机器,请直接检查日志。若有权限访问遥测数据,请监控全网状态。具体的验证步骤取决于你的权限级别——请参考本地环境的发布指南获取机器特定的命令。
需要关注的问题:
  • 日志刷屏 — 同一消息重复数百次(可能在数小时内占满磁盘)
  • 日志增长过快 — 正常情况约为1MB/小时;若增长过快则表示存在问题
  • 新的错误模式 — 发布前未出现过的错误
  • 连接失败 — 出现“connection refused”“timeout”“handshake failed”等信息
  • 资源问题 — 出现“out of memory”“no space left”“too many open files”等信息
若发现严重问题: 立即执行回滚操作、创建GitHub Issue并发布回滚通知。

Rollback

回滚流程

If a release needs to be rolled back:
bash
undefined
若需要回滚版本发布:
bash
undefined

Rollback (keeps crates.io versions)

执行回滚(保留crates.io上的版本)

./scripts/release-rollback.sh --version <VERSION>
./scripts/release-rollback.sh --version <VERSION>

Rollback and yank from crates.io (irreversible!)

执行回滚并从crates.io撤回版本(此操作不可撤销!)

./scripts/release-rollback.sh --version <VERSION> --yank-crates
./scripts/release-rollback.sh --version <VERSION> --yank-crates

Dry run

模拟回滚(仅展示操作不实际执行)

./scripts/release-rollback.sh --version <VERSION> --dry-run
undefined
./scripts/release-rollback.sh --version <VERSION> --dry-run
undefined

Version Scheme

版本号规则

  • freenet:
    0.1.X
    - patch incremented each release
  • fdev:
    0.3.X
    - patch auto-incremented by release script (independent versioning)
  • freenet:
    0.1.X
    - 每次发布递增补丁版本号
  • fdev:
    0.3.X
    - 补丁版本号由发布脚本自动递增(独立版本控制)

Incident Learnings

过往问题总结

These are real issues from past releases that the release process has been hardened against:
  • "Text file busy" during deployment — Deploy script now disables systemd auto-restart, waits for binary release, re-enables after
  • PR title must use "build:" prefix — Changed from "chore:" to comply with commit-msg hook
  • Matrix announcements can hang — matrix-send wrapper has 20s timeout and 3 retries; matrix-commander handles E2E encryption that raw curl cannot
  • PATH shadowing — Old
    cargo install freenet
    may leave stale binary at
    ~/.cargo/bin/freenet
    shadowing
    /usr/local/bin/freenet
    ; always use absolute paths when verifying versions
  • Binary vs running process mismatch — Deploying a new binary doesn't mean the service is running it; verify via
    systemctl show -p MainPID
    +
    /proc/PID/exe
    , not just binary on disk
  • Don't announce before binaries exist — Cross-compile takes 15-20 min; gateway auto-update (especially aarch64) depends on release binaries being attached
  • Log spam can fill disks — Always review logs 10-15 min after release; previous releases introduced logging that consumed disk space within hours
以下是过往发布中遇到的真实问题,发布流程已针对这些问题进行了优化:
  • 部署时出现“Text file busy”错误 — 现在部署脚本会先禁用systemd自动重启,等待二进制文件释放后再重新启用
  • PR标题必须使用“build:”前缀 — 从“chore:”改为“build:”以符合commit-msg钩子的要求
  • Matrix通知可能卡住 — matrix-send封装工具设置了20秒超时和3次重试;matrix-commander可处理原始curl无法实现的端到端加密
  • PATH路径覆盖 — 旧的
    cargo install freenet
    可能会在
    ~/.cargo/bin/freenet
    留下过期的二进制文件,覆盖
    /usr/local/bin/freenet
    ;验证版本时请始终使用绝对路径
  • 二进制文件与运行进程版本不匹配 — 部署新的二进制文件并不意味着服务正在运行该版本;请通过
    systemctl show -p MainPID
    +
    /proc/PID/exe
    进行验证,而不仅仅检查磁盘上的二进制文件
  • 在二进制文件生成前请勿发布通知 — 交叉编译需要15-20分钟;网关自动更新(尤其是aarch64架构)依赖于附加到Release的二进制文件
  • 日志刷屏可能占满磁盘 — 发布后10-15分钟务必检查日志;过往发布曾引入过在数小时内占满磁盘的日志内容

Gateway Auto-Update

网关自动更新

Gateways poll GitHub every 10 minutes for new releases and auto-update. This is pull-based (no inbound webhooks needed) and architecture-aware (x86_64/aarch64).
Peers also self-update: when a peer detects a version mismatch with the gateway (exit code 42), systemd triggers
freenet update
automatically.
Manual trigger (if you have gateway access):
gateway-auto-update.sh --force
网关每10分钟轮询GitHub一次以检查新版本并自动更新。此机制为拉取式(无需入站Webhook)且支持架构感知(x86_64/aarch64)。
节点也会自动更新:当节点检测到与网关的版本不匹配时(退出码42),systemd会自动触发
freenet update
命令。
手动触发更新(若有权限访问网关):
gateway-auto-update.sh --force

Success Criteria

成功标准

Release is complete when:
  • ✓ PR merged to main
  • ✓ Published to crates.io
  • ✓ GitHub release created with tag and binaries attached
  • ✓ Matrix announcement sent
  • ✓ River announcement sent
  • ✓ Network verified healthy post-release (logs clean, telemetry normal)
满足以下条件时,发布流程才算完成:
  • ✓ PR已合并到main分支
  • ✓ 已发布到crates.io
  • ✓ 已创建GitHub Release并附加了标签和二进制文件
  • ✓ 已发送Matrix通知
  • ✓ 已发送River通知
  • ✓ 发布后网络状态验证健康(日志无异常、遥测数据正常)