- Updated the `CONTRIBUTING.md` to include additional test commands for release asset verification and package metadata generation. - Revised `README.md` and `README.zh-CN.md` to clarify the installation process for Windows portable editions and added details on migrating from Tauri to GPUI. - Introduced new workflows for publishing to AUR, Gitee, and Homebrew, ensuring streamlined release processes across platforms. - Added a new `actionlint.yaml` for workflow syntax validation, improving CI/CD reliability. - Enhanced documentation to reflect changes in artifact versioning and release management, ensuring clarity for contributors and users.
8.5 KiB
Contributing to NyaTerm
Before changing code
Read AGENTS.md and the relevant crate-level architecture notes. Keep one
authoritative owner for each piece of state. Do not introduce WebView/Tauri
layers, #[path] module aliases, use super::*, snapshot-only stores, or direct
database access from GPUI views.
Choose the crate that owns the behavior:
- Pure models, parsing, compatibility formats, and policies belong in
nyaterm-core. - Database execution and compatibility readers belong in
nyaterm-store. - PTY, SSH, Telnet, Serial, SFTP, transfer, and tunnel runtime code belongs in
nyaterm-transport. - Terminal parsing and snapshots belong in
nyaterm-terminal; GPUI layout and painting belong innyaterm-terminal-gpui. - GPUI state, views, and background coordination belong in
nyaterm-desktop. - Shared GPUI controls and theme integration belong in
nyaterm-ui.
For a change that crosses crates, keep the boundary adapter small and document which crate owns the resulting state. Do not put filesystem, database, network, SSH, SFTP, subprocess, or image-decoding work in a render path or a long-running GPUI update callback.
Local checks
Run focused checks while iterating:
cargo check -p <crate-name> --locked
cargo test -p <crate-name> --locked
Before review, reproduce the exact Rust CI commands. Formatting and clippy run on Linux; the workspace test runs independently on Linux x64, macOS arm64, and Windows x64:
cargo fmt --all -- --check
cargo clippy --workspace --all-targets --locked
cargo test --workspace --locked --no-fail-fast
The Linux packaging-helper job, which needs neither Rust nor native GUI libraries, runs this exact command:
python -m unittest scripts.tests.test_check_release_assets scripts.tests.test_package_native scripts.tests.test_verify_native_package scripts.tests.test_generate_release_metadata
Documentation CI runs these exact commands on Linux with Python 3.12, Node.js 22, and the repository-pinned pnpm version:
python3 scripts/ci/check_docs_translations.py
pnpm --dir docs-site install --frozen-lockfile
pnpm --dir docs-site build
cargo test --workspace builds every test target, so a separate cargo check --workspace before it is redundant. --no-fail-fast matters: without it the
first failing crate hides every crate after it. The non-ignored RDP and VNC
helper lifecycle integration tests are included automatically in the workspace
test; they can also be reproduced directly:
cargo test -p nyaterm-rdp-helper --test lifecycle --locked
cargo test -p nyaterm-vnc-helper --test lifecycle --locked
Use cargo run -p nyaterm-app --bin nyaterm for a local graphical smoke test.
That command builds only the application, not the RDP/VNC helpers. Build the
helpers first when the smoke test includes those protocols:
cargo build -p nyaterm-rdp-helper -p nyaterm-vnc-helper --locked
The full workspace and application checks may need platform-native GPUI, PTY, serial, clipboard, and window-system dependencies.
Ignored benchmarks and SFTP integration test
Ignored benchmarks are manual diagnostics, not CI gates. Run them by exact test
name in a release build on a recorded, otherwise idle machine; do not run a
blanket workspace --ignored, which would also select credentialed integration
tests and unrelated ignored fixtures:
cargo test -p nyaterm-desktop --release --locked dense_action_link_selection_drag_benchmark -- --ignored --nocapture --test-threads=1
cargo test -p nyaterm-desktop --release --locked overview_marker_fast_scroll_benchmark -- --ignored --nocapture --test-threads=1
cargo test -p nyaterm-desktop --release --locked selected_occurrence_search_large_scrollback_benchmark -- --ignored --nocapture --test-threads=1
cargo test -p nyaterm-desktop --release --locked root_render_hundred_sessions_eight_terminal_leaves_benchmark -- --ignored --nocapture --test-threads=1
cargo test -p nyaterm-terminal-gpui --release --locked keyword_highlight_benchmark -- --ignored --nocapture --test-threads=1
cargo test -p nyaterm-core --release --locked sustained_in_place_input_and_deletion -- --ignored --nocapture --test-threads=1
A benchmark exiting successfully means only that its assertions did not fail; elapsed output is not a portable performance threshold. Record the commit, OS/architecture, CPU/GPU, display scale, font, build profile, workload, sample count, and raw output before comparing runs.
The ignored SFTP end-to-end test requires
NYATERM_TEST_SFTP_HOST, NYATERM_TEST_SFTP_PORT,
NYATERM_TEST_SFTP_USERNAME, NYATERM_TEST_SFTP_PASSWORD, and
NYATERM_TEST_SFTP_ROOT. The root must already exist, be writable, and be safe
for the test to create and remove children. Use only an isolated test server and
disposable root, keep credentials out of command lines and logs, then run:
cargo test -p nyaterm-transport --test sftp_service_e2e --locked sftp_service_round_trips_file_manager_operations -- --ignored --nocapture --test-threads=1
Release packaging matrix
Release CI packages and verifies six native targets:
| Runner | Rust target | Artifacts |
|---|---|---|
| macOS arm64 | aarch64-apple-darwin |
.dmg, .app.tar.gz |
| macOS x64 | x86_64-apple-darwin |
.dmg, .app.tar.gz |
| Linux x64 | x86_64-unknown-linux-gnu |
.AppImage, .deb, .rpm |
| Linux arm64 | aarch64-unknown-linux-gnu |
.AppImage, .deb, .rpm |
| Windows x64 | x86_64-pc-windows-msvc |
_portable.zip, -setup.exe |
| Windows arm64 | aarch64-pc-windows-msvc |
_portable.zip, -setup.exe |
The release preflight uses the same locked workspace test and Python packaging
unit tests shown above. Each matrix leg runs package_native.py and
verify_native_package.py; publishing additionally checks that the combined
asset set is exact. Those automated checks validate package structure,
metadata, helper presence, and binary architecture. They do not replace manual
installation, launch, upgrade/uninstall, URL-handler, platform trust/signing,
GUI, PTY, GPU/IME, or real RDP/VNC acceptance on the target OS.
NYATERM_ARTIFACT_VERSION changes only the version segment in artifact names;
package metadata still uses the workspace SemVer. This is reserved for the
manual snapshot workflow and must be passed to both packaging and verification:
NYATERM_ARTIFACT_VERSION=main-snapshot \
python scripts/release/package_native.py "${TARGET}"
python scripts/release/verify_native_package.py \
--target "${TARGET}" --version "${VERSION}" \
--artifact-version main-snapshot --dist dist
Tag releases publish the verified assets to GitHub and Cloudflare R2, then
trigger the Gitee, AUR, and Homebrew workflows. downloads.json is the website
download catalog; the signed latest.json exists only to migrate installed
Tauri releases. A manual Main Snapshot run overwrites the main-snapshot
prerelease and does not publish to downstream channels. Release builds require
the repository variables and secrets named by those workflows; missing release
configuration is a hard failure.
Tests should live beside the behavior they cover. Storage, credentials, encryption, backup, cloud-sync, known-host, and session changes must include new-data round trips and representative legacy-data tests. Never log passwords, private keys, OTP secrets, API keys, or unredacted terminal context.
Pull requests
Use a Conventional Commit-style subject, for example
fix(transport): handle closed SSH channels. Describe behavior, architectural
ownership, commands and platforms tested, and any persistence, credential,
migration, or forked-dependency impact. Keep unrelated formatting or
generated metadata out of the change.
Keep pull requests focused and explain compatibility-sensitive decisions in the
description. Patched third-party dependencies are not vendored: each is a patch
series on a fork under https://github.com/nyakang on branch nyaterm, pinned
by revision in the root Cargo.toml. Change one by committing to its fork
branch and bumping that revision, and identify the upstream project/version or
commit, the reason for the modification, and the validation performed. temp/vendor/
holds untracked read-only copies for reading only; nothing there is compiled.
Compatibility
Preserve existing table names, keys, serialized field names, document keys, encryption prefixes, master-key wrapping, backup formats, and fallback decryption behavior unless the change includes a tested migration path. Do not overwrite user data until validation succeeds, and keep secret-bearing values masked when returning settings to the UI.