Compare commits
5
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0fbcb7adbf | ||
|
|
43b5f81d51 | ||
|
|
533d7aa3a1 | ||
|
|
ee6633c401 | ||
|
|
1f330212e8 |
No files matched your search
@@ -6,7 +6,9 @@
|
||||
# linux AppImage
|
||||
# publish (environment `release`, approved by hand) uploads to R2 behind
|
||||
# dl.shellrs.com, creates the GitHub release, and only then
|
||||
# replaces the channel's manifest, which is what clients follow
|
||||
# replaces the channel's manifest, which is what clients follow;
|
||||
# the manifest lists the GitHub release as each package's
|
||||
# second address
|
||||
#
|
||||
# A tag with a pre-release (v0.3.0-beta.1) goes to the beta channel only. A
|
||||
# stable release also becomes the beta channel's, unless beta is ahead.
|
||||
@@ -284,6 +286,10 @@ jobs:
|
||||
- name: Manifests, last
|
||||
env:
|
||||
MINISIGN_PASSWORD: ${{ secrets.MINISIGN_PASSWORD }}
|
||||
# The GitHub release just created: clients try it when
|
||||
# dl.shellrs.com fails. The repository is public, so it needs no
|
||||
# sign-in.
|
||||
SHELLRS_MIRROR_BASE: ${{ github.server_url }}/${{ github.repository }}/releases/download/v${{ needs.verify.outputs.version }}
|
||||
run: |
|
||||
publish() {
|
||||
packaging/make-manifest.sh "$VERSION" "$1" notes.md dist "$1.json"
|
||||
|
||||
@@ -16,3 +16,18 @@ ShellRS 的第一个公开版本。
|
||||
- 端口转发:本地、远程和动态转发,断线后自动重连,可随 ShellRS 一起启动。
|
||||
- 外部 CLI:`shellrs` 命令让 AI Agent 用已保存的主机执行命令、传输文件。
|
||||
- 在线升级:在后台检查并下载新版本,下好后标题栏右上角提示,重启或退出时安装。
|
||||
|
||||
## [0.1.0-beta.1]
|
||||
|
||||
ShellRS 的第一个测试版本,只发到 Beta 渠道,用来验证安装和在线升级。之后的测试版会通过在线升级自动送达。
|
||||
|
||||
### 新增
|
||||
|
||||
- 主机与分组:持久保存,分组可以多层嵌套,支持搜索和拖动整理。
|
||||
- 凭据:密码、密钥(本机文件、粘贴或生成新密钥)和 SSH Agent,多台主机可以共用一条凭据。
|
||||
- 连接方式:直接连接、SSH 跳板或 HTTP / SOCKS5 代理。
|
||||
- 终端:本地终端和多个 SSH 终端,支持查找、清屏和延迟显示。
|
||||
- SFTP:对标 WinSCP 的双栏文件浏览器,上传和下载都支持断点续传和传输队列。
|
||||
- 端口转发:本地、远程和动态转发,断线后自动重连,可随 ShellRS 一起启动。
|
||||
- 外部 CLI:`shellrs` 命令让 AI Agent 用已保存的主机执行命令、传输文件。
|
||||
- 在线升级:在后台检查并下载新版本,下好后标题栏右上角提示,重启或退出时安装。
|
||||
@@ -10,7 +10,7 @@ ShellRS(crate 与二进制都叫 `shellrs`)是一个类似 Xshell / WinSCP
|
||||
|
||||
主机和分组是**真实持久化**的,存在一个 SQLite 文件里(`~/Library/Application Support/shellrs/shellrs.db`,`SHELLRS_DATA_DIR` 可覆盖目录)。本地终端(`portable-pty` + `alacritty_terminal`)和 SSH 远程连接(`russh`)也都是真的。密码与私钥口令存在系统钥匙串里(`keyring`),**数据库里永远不出现秘密**。SFTP 双栏浏览、上传、下载和文件操作(删除、重命名、属性、新建)也已接入真实文件系统,上传和下载都支持断点续传,并按 WinSCP 的方式排队(每个 SFTP 标签一个传输队列);目录同步尚未实现。SSH 端口转发(本地 `-L`、远程 `-R`、动态 `-D`)也是真的,规则和主机存在同一个库里。凭据(密码 / 密钥 / SSH Agent)也存在这个库里(密码和口令照旧只进钥匙串,粘贴或生成的私钥是数据目录 `keys/` 下的文件),主机可以「使用凭据」而不是自己填登录信息。主机还有「连接方式」:直接连接、经过别的主机做 SSH 跳板(可多级)、或经由 HTTP / SOCKS5 代理,终端、SFTP、端口转发、外部 CLI 和测试连接都照它走。详见 `README.md`。
|
||||
|
||||
已确认的产品决定:WinSCP 式双栏文件浏览器是「SFTP」Dock 标签页,和终端一样每次「打开 SFTP」都新开一个(同一主机可以开多个,各自独立连接),操作逻辑对标 WinSCP Commander(两行工具栏、路径标签、WinSCP 的列、列表右键菜单、高亮多选;面板顶上不再有「用户@主机:端口」一行;本地侧与远程侧对称,本地删除进废纸篓;书签按主机、按本地 / 远程各一份持久化);传输进行中还能再发起传输,新批次在 SFTP 标签底部的「传输队列」里排队依次执行(WinSCP 的队列面板,不做前台进度对话框);暂不做 Dock 布局持久化、过滤、查找文件和目录树;首次启动是空库,不预置任何分组或主机;分组支持任意层级嵌套,主机也可以不属于任何分组(渲染在树的根层级);删除分组会连同其子分组和里面的主机一起删,删除前确认并写明数量。端口转发不是 Dock 标签页,而是侧栏的另一个列表,由标题栏「ShellRS」后面的三个图标(主机 / 端口转发 / 凭据)切换;一条规则经由一个已保存的主机,启动时自己建一条 SSH 连接,不计入主机的连接状态,主机「断开连接」不停它;删除主机(或含它的分组)连同经由它的规则一起删,确认框写明数量;规则可设「启动 ShellRS 时自动开启」,「创建」只保存不启动;新建规则时「经由主机」留空(不预选当前标签的主机,也不预选第一台),由用户自己选;断线后按 1、3、10 秒自动重连三次,重连不弹任何问答;配置对话框用排成一行的三张类型卡片、实时示意图、一句话说明和一直循环的流向动画说明三种转发,示意图和那句话里的服务器按角色叫「SSH 服务器」,不写所选主机的名称;暂不做转发的外部 CLI 接口、规则排序和监听端口 0。凭据是侧栏的第三个列表(密码 / 密钥 / SSH Agent 三种),**凭据带用户名**:主机「使用凭据」时不再填用户名,改凭据的用户名所有用它的主机一起变;主机对话框的「认证方式」是三选一:「密码」(只有用户名和密码,密码留空就每次连接时询问,不悄悄试密钥)、「使用凭据」和「无密码」(只有用户名:依次试服务器免认证、SSH Agent 和 `~/.ssh` 的默认私钥,服务器要求密码时直接报错、不询问;密钥之后再要验证码照样问);主机自己不再有私钥文件,要用私钥就建密钥凭据;密钥凭据的私钥有三种来源——「本机文件」(只引用路径,不导入内容)、「粘贴」和「生成新密钥」(Ed25519 默认,另有 RSA 4096)——在同一个对话框里(类型选「密钥」后多一排来源单选),不按类型拆对话框,因为编辑时要能改类型、换钥匙,用它的主机一起跟着变;粘贴和生成的私钥由 ShellRS 写成数据目录 `keys/` 下的文件(不进钥匙串:Windows 凭据管理器一条最多 2560 字节,RSA 私钥放不下),凭据引用它的路径,编辑时就显示为「本机文件」;空列表和空白处的右键菜单多一个「生成密钥…」,打开的是同一个对话框、已选好「密钥 · 生成新密钥」,密钥凭据的右键菜单有「复制公钥」;删除仍在用的凭据要确认并写明台数,删除后那些主机保留用户名,密码凭据的改成「密码」(连接时询问),密钥和 Agent 凭据的改成「无密码」(`CredentialKind::without_credential`),密码和私钥不复制过去,已打开的连接不断开;主机对话框里不做「新建凭据…」(设计规范不叠弹层);Windows 上 Agent 走 OpenSSH Agent 的命名管道,「无密码」也试它;暂不做自定义 Agent 套接字、Pageant、凭据的外部 CLI 接口和凭据排序。主机对话框「分组」下面是「连接方式」三选一:「直接连接」(默认)、「SSH 跳板」和「代理连接」。跳板选的是已保存的主机,可多级,**只走这里列出的链**:跳板主机自己的连接方式不参与(所以不会成环),每台用它自己的地址、端口、认证和 known_hosts 条目;跳板列表不做拖动排序(删了重加)。代理是 HTTP(`CONNECT`)或 SOCKS5(域名交给代理解析),用户名和密码可选,密码按「代理地址 + 用户名」进钥匙串(`SecretRef::Proxy`),代理要求认证或拒绝时直接报错、不弹问答。跳板和代理不叠加。删除被别的主机用作跳板的主机:确认框写明台数,那些主机的跳板列表里留下「已删除的主机」占位(库里 `ON DELETE SET NULL`),连接时直接报错,不悄悄改成直连或少跳一级,表单里留着占位就保存会报错;删除不重连已打开的连接。在线升级:主域名 sLine truncated
|
||||
已确认的产品决定:WinSCP 式双栏文件浏览器是「SFTP」Dock 标签页,和终端一样每次「打开 SFTP」都新开一个(同一主机可以开多个,各自独立连接),操作逻辑对标 WinSCP Commander(两行工具栏、路径标签、WinSCP 的列、列表右键菜单、高亮多选;面板顶上不再有「用户@主机:端口」一行;本地侧与远程侧对称,本地删除进废纸篓;书签按主机、按本地 / 远程各一份持久化);传输进行中还能再发起传输,新批次在 SFTP 标签底部的「传输队列」里排队依次执行(WinSCP 的队列面板,不做前台进度对话框);暂不做 Dock 布局持久化、过滤、查找文件和目录树;首次启动是空库,不预置任何分组或主机;分组支持任意层级嵌套,主机也可以不属于任何分组(渲染在树的根层级);删除分组会连同其子分组和里面的主机一起删,删除前确认并写明数量。端口转发不是 Dock 标签页,而是侧栏的另一个列表,由标题栏「ShellRS」后面的三个图标(主机 / 端口转发 / 凭据)切换;一条规则经由一个已保存的主机,启动时自己建一条 SSH 连接,不计入主机的连接状态,主机「断开连接」不停它;删除主机(或含它的分组)连同经由它的规则一起删,确认框写明数量;规则可设「启动 ShellRS 时自动开启」,「创建」只保存不启动;新建规则时「经由主机」留空(不预选当前标签的主机,也不预选第一台),由用户自己选;断线后按 1、3、10 秒自动重连三次,重连不弹任何问答;配置对话框用排成一行的三张类型卡片、实时示意图、一句话说明和一直循环的流向动画说明三种转发,示意图和那句话里的服务器按角色叫「SSH 服务器」,不写所选主机的名称;暂不做转发的外部 CLI 接口、规则排序和监听端口 0。凭据是侧栏的第三个列表(密码 / 密钥 / SSH Agent 三种),**凭据带用户名**:主机「使用凭据」时不再填用户名,改凭据的用户名所有用它的主机一起变;主机对话框的「认证方式」是三选一:「密码」(只有用户名和密码,密码留空就每次连接时询问,不悄悄试密钥)、「使用凭据」和「无密码」(只有用户名:依次试服务器免认证、SSH Agent 和 `~/.ssh` 的默认私钥,服务器要求密码时直接报错、不询问;密钥之后再要验证码照样问);主机自己不再有私钥文件,要用私钥就建密钥凭据;密钥凭据的私钥有三种来源——「本机文件」(只引用路径,不导入内容)、「粘贴」和「生成新密钥」(Ed25519 默认,另有 RSA 4096)——在同一个对话框里(类型选「密钥」后多一排来源单选),不按类型拆对话框,因为编辑时要能改类型、换钥匙,用它的主机一起跟着变;粘贴和生成的私钥由 ShellRS 写成数据目录 `keys/` 下的文件(不进钥匙串:Windows 凭据管理器一条最多 2560 字节,RSA 私钥放不下),凭据引用它的路径,编辑时就显示为「本机文件」;空列表和空白处的右键菜单多一个「生成密钥…」,打开的是同一个对话框、已选好「密钥 · 生成新密钥」,密钥凭据的右键菜单有「复制公钥」;删除仍在用的凭据要确认并写明台数,删除后那些主机保留用户名,密码凭据的改成「密码」(连接时询问),密钥和 Agent 凭据的改成「无密码」(`CredentialKind::without_credential`),密码和私钥不复制过去,已打开的连接不断开;主机对话框里不做「新建凭据…」(设计规范不叠弹层);Windows 上 Agent 走 OpenSSH Agent 的命名管道,「无密码」也试它;暂不做自定义 Agent 套接字、Pageant、凭据的外部 CLI 接口和凭据排序。主机对话框「分组」下面是「连接方式」三选一:「直接连接」(默认)、「SSH 跳板」和「代理连接」。跳板选的是已保存的主机,可多级,**只走这里列出的链**:跳板主机自己的连接方式不参与(所以不会成环),每台用它自己的地址、端口、认证和 known_hosts 条目;跳板列表不做拖动排序(删了重加)。代理是 HTTP(`CONNECT`)或 SOCKS5(域名交给代理解析),用户名和密码可选,密码按「代理地址 + 用户名」进钥匙串(`SecretRef::Proxy`),代理要求认证或拒绝时直接报错、不弹问答。跳板和代理不叠加。删除被别的主机用作跳板的主机:确认框写明台数,那些主机的跳板列表里留下「已删除的主机」占位(库里 `ON DELETE SET NULL`),连接时直接报错,不悄悄改成直连或少跳一级,表单里留着占位就保存会报错;删除不重连已打开的连接。在线升级:主域名 sLine truncated
|
||||
|
||||
做 UI 之前先读 `gpui-kit` 与 `gpui-kit-design-guides` 两个技能(其中的 Coding Guides 和 Design Guides 在本仓库是规范,不是参考)。不要凭记忆臆造 gpui-kit API:以 `~/.cargo/registry/src/*/gpui-component-0.6.1/`、`gpui-base-0.6.1/` 的源码或 `https://gpui-kit.com/component/<name>.md` 为准。
|
||||
|
||||
|
||||
Generated
+1
-1
@@ -7686,7 +7686,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "shellrs"
|
||||
version = "0.1.0"
|
||||
version = "0.1.0-beta.1"
|
||||
dependencies = [
|
||||
"alacritty_terminal",
|
||||
"anyhow",
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "shellrs"
|
||||
version = "0.1.0"
|
||||
version = "0.1.0-beta.1"
|
||||
edition = "2024"
|
||||
publish = false
|
||||
description = "SSH session manager with local terminal support"
|
||||
|
||||
@@ -292,7 +292,7 @@ ShellRS 启动 30 秒后检查一次有没有新版本,之后每 6 小时检
|
||||
|
||||
1. 核对 tag 与 `Cargo.toml` 一致,截出更新说明,确认代码里有发布公钥;
|
||||
2. 构建并打包:macOS 合成 universal,签名、公证、staple,产出升级用的 `.app.zip` 和首次安装用的 `.dmg`;Windows 用 Inno Setup 打安装程序;Linux 打 AppImage;
|
||||
3. 在 `release` 环境里人工批准后:给每个包签名,上传到 R2(`dl.shellrs.com/releases/<版本>/`),建 GitHub Release,**最后**才替换更新清单 `dl.shellrs.com/update/v1/<通道>.json` 并清 CDN 缓存。
|
||||
3. 在 `release` 环境里人工批准后:给每个包签名,上传到 R2(`dl.shellrs.com/releases/<版本>/`),建 GitHub Release,**最后**才替换更新清单 `dl.shellrs.com/update/v1/<通道>.json` 并清 CDN 缓存。清单里每个包有两个下载地址:先 R2,下载失败时客户端接着试 GitHub Release(仓库是公开的,下载不用登录)。
|
||||
|
||||
版本号带 `-` 的(如 `0.3.0-beta.1`)只发到 beta 通道;正式版同时成为 beta 通道的最新版。在 Actions 里手动运行这个 workflow 只构建打包、不发布,用来演练。客户端只接受比自己新的版本,所以发错的版本撤不回来:把清单改回上一版能阻止更多人升级,修复要发新的补丁版。
|
||||
|
||||
|
||||
@@ -9,22 +9,34 @@
|
||||
"notes_url": "https://shellrs.com/changelog#0.2.0",
|
||||
"assets": {
|
||||
"macos-aarch64": {
|
||||
"urls": ["https://dl.shellrs.com/releases/0.2.0/ShellRS-0.2.0-macos-universal.app.zip"],
|
||||
"urls": [
|
||||
"https://dl.shellrs.com/releases/0.2.0/ShellRS-0.2.0-macos-universal.app.zip",
|
||||
"https://github.com/since2006/shell-rs/releases/download/v0.2.0/ShellRS-0.2.0-macos-universal.app.zip"
|
||||
],
|
||||
"size": 41234567,
|
||||
"sha256": "0000000000000000000000000000000000000000000000000000000000000000"
|
||||
},
|
||||
"macos-x86_64": {
|
||||
"urls": ["https://dl.shellrs.com/releases/0.2.0/ShellRS-0.2.0-macos-universal.app.zip"],
|
||||
"urls": [
|
||||
"https://dl.shellrs.com/releases/0.2.0/ShellRS-0.2.0-macos-universal.app.zip",
|
||||
"https://github.com/since2006/shell-rs/releases/download/v0.2.0/ShellRS-0.2.0-macos-universal.app.zip"
|
||||
],
|
||||
"size": 41234567,
|
||||
"sha256": "0000000000000000000000000000000000000000000000000000000000000000"
|
||||
},
|
||||
"windows-x86_64": {
|
||||
"urls": ["https://dl.shellrs.com/releases/0.2.0/ShellRS-0.2.0-windows-x86_64-setup.exe"],
|
||||
"urls": [
|
||||
"https://dl.shellrs.com/releases/0.2.0/ShellRS-0.2.0-windows-x86_64-setup.exe",
|
||||
"https://github.com/since2006/shell-rs/releases/download/v0.2.0/ShellRS-0.2.0-windows-x86_64-setup.exe"
|
||||
],
|
||||
"size": 18234567,
|
||||
"sha256": "1111111111111111111111111111111111111111111111111111111111111111"
|
||||
},
|
||||
"linux-x86_64": {
|
||||
"urls": ["https://dl.shellrs.com/releases/0.2.0/ShellRS-0.2.0-linux-x86_64.AppImage"],
|
||||
"urls": [
|
||||
"https://dl.shellrs.com/releases/0.2.0/ShellRS-0.2.0-linux-x86_64.AppImage",
|
||||
"https://github.com/since2006/shell-rs/releases/download/v0.2.0/ShellRS-0.2.0-linux-x86_64.AppImage"
|
||||
],
|
||||
"size": 28234567,
|
||||
"sha256": "2222222222222222222222222222222222222222222222222222222222222222"
|
||||
}
|
||||
|
||||
@@ -31,10 +31,14 @@ pub const DOWNLOAD_PAGE: &str = "https://shellrs.com/download";
|
||||
/// and a spare kept offline so the first can be replaced. Rotating means
|
||||
/// shipping a release that knows the new key before signing with it.
|
||||
///
|
||||
/// Empty until the release keys exist (see the release section of
|
||||
/// `README.md`); the release workflow refuses to build a release without
|
||||
/// them, and a build without them rejects every manifest.
|
||||
pub const TRUSTED_KEYS: &[&str] = &[];
|
||||
/// The release workflow refuses to build a release while this is empty: a
|
||||
/// build without keys rejects every manifest.
|
||||
pub const TRUSTED_KEYS: &[&str] = &[
|
||||
// In use: the release workflow signs with it (key id CD239E668A535CB0).
|
||||
"RWSwXFOKZp4jzaKmM9EkpY3iIyI0vMzi4EhFDlXwGy+XYiaHIWZY4ELa",
|
||||
// Spare, kept offline (key id F3B9F08DE80AF399).
|
||||
"RWSZ8wrojfC584RC+h7Frcp/pDW0pd7TaB4pO6bTVVOgSj6mo1KFs0sh",
|
||||
];
|
||||
|
||||
/// Which stream of releases a copy follows. Beta also gets every stable
|
||||
/// release that is not behind it.
|
||||
|
||||
+10
-1
@@ -335,6 +335,11 @@ pub(crate) mod tests {
|
||||
.arg(&out)
|
||||
.env("MINISIGN_KEY_FILE", &secret)
|
||||
.env_remove("MINISIGN_PASSWORD")
|
||||
// As the release workflow sets it.
|
||||
.env(
|
||||
"SHELLRS_MIRROR_BASE",
|
||||
"https://github.com/since2006/shell-rs/releases/download/v0.2.0",
|
||||
)
|
||||
.output()
|
||||
.unwrap();
|
||||
assert!(made.status.success(), "{made:?}");
|
||||
@@ -349,9 +354,13 @@ pub(crate) mod tests {
|
||||
assert_eq!(manifest.notes, "### 新增\n\n- 在线升级\n");
|
||||
let mac = &manifest.assets["macos-aarch64"];
|
||||
assert_eq!(mac, &manifest.assets["macos-x86_64"]);
|
||||
// dl.shellrs.com first, the GitHub release only when it fails.
|
||||
assert_eq!(
|
||||
mac.urls,
|
||||
["https://dl.shellrs.com/releases/0.2.0/ShellRS-0.2.0-macos-universal.app.zip"]
|
||||
[
|
||||
"https://dl.shellrs.com/releases/0.2.0/ShellRS-0.2.0-macos-universal.app.zip",
|
||||
"https://github.com/since2006/shell-rs/releases/download/v0.2.0/ShellRS-0.2.0-macos-universal.app.zip",
|
||||
]
|
||||
);
|
||||
let package = dist.join("ShellRS-0.2.0-linux-x86_64.AppImage");
|
||||
assert_eq!(
|
||||
|
||||
Reference in new issue
Block a user