diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 7fd486c..aa97e73 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -44,6 +44,23 @@ jobs: shell: bash run: echo "VERSION=${GITHUB_REF_NAME#v}" >> $GITHUB_OUTPUT + - name: Read release notes + id: notes + shell: bash + run: | + NOTES_FILE="releases/v${{ steps.version.outputs.VERSION }}.md" + if [ -f "$NOTES_FILE" ]; then + echo "HAS_NOTES=true" >> $GITHUB_OUTPUT + # 使用 EOF 分隔符避免特殊字符问题 + echo "NOTES<> $GITHUB_OUTPUT + cat "$NOTES_FILE" >> $GITHUB_OUTPUT + echo "" >> $GITHUB_OUTPUT + echo "EOF" >> $GITHUB_OUTPUT + else + echo "HAS_NOTES=false" >> $GITHUB_OUTPUT + echo "NOTES=Release v${{ steps.version.outputs.VERSION }}" >> $GITHUB_OUTPUT + fi + - name: Build executable run: | python -m nuitka ` @@ -64,6 +81,7 @@ jobs: - name: Upload to Release uses: softprops/action-gh-release@v1 with: + body: ${{ steps.notes.outputs.NOTES }} files: sbackup-${{ steps.version.outputs.VERSION }}-windows-x64.exe # 构建 macOS 可执行文件 @@ -87,6 +105,21 @@ jobs: id: arch run: echo "ARCH=$(uname -m)" >> $GITHUB_OUTPUT + - name: Read release notes + id: notes + run: | + NOTES_FILE="releases/v${{ steps.version.outputs.VERSION }}.md" + if [ -f "$NOTES_FILE" ]; then + echo "HAS_NOTES=true" >> $GITHUB_OUTPUT + echo "NOTES<> $GITHUB_OUTPUT + cat "$NOTES_FILE" >> $GITHUB_OUTPUT + echo "" >> $GITHUB_OUTPUT + echo "EOF" >> $GITHUB_OUTPUT + else + echo "HAS_NOTES=false" >> $GITHUB_OUTPUT + echo "NOTES=Release v${{ steps.version.outputs.VERSION }}" >> $GITHUB_OUTPUT + fi + - name: Build executable run: | python -m nuitka \ @@ -107,6 +140,7 @@ jobs: - name: Upload to Release uses: softprops/action-gh-release@v1 with: + body: ${{ steps.notes.outputs.NOTES }} files: sbackup-${{ steps.version.outputs.VERSION }}-macos-${{ steps.arch.outputs.ARCH }} # 构建 Linux 可执行文件 @@ -130,6 +164,21 @@ jobs: id: arch run: echo "ARCH=$(uname -m)" >> $GITHUB_OUTPUT + - name: Read release notes + id: notes + run: | + NOTES_FILE="releases/v${{ steps.version.outputs.VERSION }}.md" + if [ -f "$NOTES_FILE" ]; then + echo "HAS_NOTES=true" >> $GITHUB_OUTPUT + echo "NOTES<> $GITHUB_OUTPUT + cat "$NOTES_FILE" >> $GITHUB_OUTPUT + echo "" >> $GITHUB_OUTPUT + echo "EOF" >> $GITHUB_OUTPUT + else + echo "HAS_NOTES=false" >> $GITHUB_OUTPUT + echo "NOTES=Release v${{ steps.version.outputs.VERSION }}" >> $GITHUB_OUTPUT + fi + - name: Build executable run: | python -m nuitka \ @@ -150,4 +199,5 @@ jobs: - name: Upload to Release uses: softprops/action-gh-release@v1 with: + body: ${{ steps.notes.outputs.NOTES }} files: sbackup-${{ steps.version.outputs.VERSION }}-linux-${{ steps.arch.outputs.ARCH }} diff --git a/releases/TEMPLATE.md b/releases/TEMPLATE.md new file mode 100644 index 0000000..0da72c3 --- /dev/null +++ b/releases/TEMPLATE.md @@ -0,0 +1,38 @@ + + +## What's New + +- 新增功能说明 + +## Improvements + +- 改进项说明 + +## Bug Fixes + +- 修复说明 + +## Breaking Changes + +- 不兼容变更(如无则删除此节) + +## Installation + +```bash +pip install sbackup-cli +``` + +**Binary downloads:** + +| Platform | File | +|----------|------| +| Windows x64 | `sbackup-{version}-windows-x64.exe` | +| macOS ARM64 | `sbackup-{version}-macos-arm64` | +| macOS x64 | `sbackup-{version}-macos-x86_64` | +| Linux x64 | `sbackup-{version}-linux-x86_64` | + +**Full Changelog**: https://github.com/xiatianxuan/sbackup/compare/v{prev}...v{current} diff --git a/releases/v1.0.1.md b/releases/v1.0.1.md new file mode 100644 index 0000000..af92ba4 --- /dev/null +++ b/releases/v1.0.1.md @@ -0,0 +1,53 @@ +## What's New + +### Remote Backup Improvements + +- **SFTP**: Separated `start_client` / `auth` steps for cleaner authentication flow +- **SFTP**: Auto-save host keys to `known_hosts` on first connection +- **SFTP**: Support non-standard port host key lookup +- **SFTP**: New `allow_password_fallback` parameter to control private key auth fallback behavior +- **WebDAV**: Custom opener now properly handles PROPFIND redirects while preserving auth headers and request method + +### Bug Fixes + +- Fixed `webdav` / `cloud` upload where `uploaded_files` was not collected in `_upload_to_cloud()` +- Fixed `--debug` mode not taking effect due to missing `force=True` in `logging.basicConfig` + +### Documentation + +- README translated to 9 languages (EN/ZH/DE/ES/FR/JA/KO/PT/RU) +- All READMEs include shields.io badges and language switcher +- Updated command list to 37 commands +- Updated code structure to 37 modules + +### Internationalization + +- Completed translations for all 9 languages (665 keys each, 0 missing) +- Removed 4 obsolete `cmd.remote.*` keys from all locales + +### CI/CD + +- New CI workflow: pytest runs on push/PR to dev/main (3 platforms x 2 Python versions) +- Release workflow: binary filenames now include version, platform, and architecture +- Release workflow: reads `releases/v{version}.md` for GitHub Release description +- Nuitka build: added missing dependencies (paramiko, minio, reedsolo, watchdog) + +### Testing + +- 940 tests passed, 0 failed +- Fixed test state pollution: locale and logging level now properly restored in tearDown + +## Installation + +```bash +pip install sbackup-cli +``` + +**Binary downloads:** + +| Platform | File | +|----------|------| +| Windows x64 | `sbackup-1.0.1-windows-x64.exe` | +| macOS ARM64 | `sbackup-1.0.1-macos-arm64` | +| macOS x64 | `sbackup-1.0.1-macos-x86_64` | +| Linux x64 | `sbackup-1.0.1-linux-x86_64` |