Files
nyaterm/CONTRIBUTING.md
T
Kang 8e27865206 ci(contributing, docs): enhance contribution guidelines and installation instructions
- 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.
2026-08-31 10:32:18 +08:00

186 lines
8.5 KiB
Markdown

# 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 in `nyaterm-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:
```bash
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:
```bash
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:
```bash
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:
```bash
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:
```bash
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:
```bash
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:
```bash
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:
```bash
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:
```bash
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.