From 1b579271e552fae8d4c7c3c9112a98a954b70e60 Mon Sep 17 00:00:00 2001 From: naturallaw777 <99053422+naturallaw777@users.noreply.github.com> Date: Wed, 29 Jul 2026 16:36:35 +0000 Subject: [PATCH] docs: write real v1.0.4 changelog and auto-generate release notes in release script - CHANGELOG.md: replace v1.0.4 placeholder section with the actual changes (Lightning Wallet Connections/NWC, Hub version badges, backup overhaul, automated releases, security hardening, fixes) - release-stable.sh: generate categorized Keep-a-Changelog release notes from commits since the last tag (feat/fix/docs/security grouping), let the user review/edit before publishing, and use the same notes for CHANGELOG.md, the GitHub release, and the Gitea release - Fix broken /api/ path in the v1.0.4 changelog release link - Build Gitea API payload with jq/python so multi-line notes are JSON-safe Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com> --- CHANGELOG.md | 40 ++++++++++-- scripts/release-stable.sh | 127 +++++++++++++++++++++++++++++++------- 2 files changed, 142 insertions(+), 25 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4a4daa2..0ca3f1b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,15 +10,47 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [1.0.4] - 2026-07-29 ### Added -- (Add new features here) +- **Lightning Wallet Connections (NWC)** — Hub-managed Nostr Wallet Connect powered by Alby Hub + LND: + - Create, view, and delete wallet connections directly from the Sovran Hub with a tabbed modal UI + - Downloadable/printable LNURL QR codes for connecting external wallets + - Channel liquidity guide and onboarding guidance for new LND nodes + - Unique-hostname enforcement with conflict validation and UI guidance + - Official NWC branding and logo +- **Version visibility across the Hub**: + - Sovran_SystemsOS version badge displayed under the Hub title + - Version numbers shown on all Hub service tiles and next to service modal titles + - Deployed PHP app versions surfaced in service titles + - Build-time version reference file (`VERSION`) so version lookups are instantaneous and consistent +- **Automated stable release workflow** (`scripts/release-stable.sh`) with versioned ISO naming from the `VERSION` file +- `CONTRIBUTING.md` and expanded project documentation ### Changed -- (Add changes here) +- **Manual Backup overhauled**: replaced tar+DB+LND archive approach with a reliable ext4 + rsync workflow, including + mount checks, path safety, atomic completion markers, stale-marker cleanup, and behavioral test coverage +- **Port-forwarding UX simplified**: removed onboarding Step 4 and the misleading local "ready" status; + Njal.la DDNS now runs automatically when the feature is enabled +- README restructured for clarity, links, and accuracy; added router/ISP port-forwarding requirements + for Server + Desktop mode; acknowledged LiveKit and Alby Hub +- Updated nixpkgs and Bitcoin clients +- Repository cleanup: removed unused `.github`, `.tests`, `nix/`, and `docs/ai` directories ### Fixed -- (Add bug fixes here) +- NWC wallet certificate path wiring (now uses the nix-bitcoin LND cert path) +- Deterministic LND/Alby Hub port collision +- Alby Hub executable resolution and v1.23.0 patches regenerated against exact upstream source +- Manual Backup exit-code failures (bash/gawk in service PATH, tar tolerance, flock, browser-cache exclusions) +- rsync destination-directory failures in backups (auto `mkdir -p`, mount check, 19 behavioral tests) +- `sovran-hosts-update` converted to `writeShellApplication` with explicit runtime inputs +- Incorrect `lib.mkIf` usage in the NWC wallets module +- Duplicate systemd LND strings +- `git fetch` tag-clobber errors against Gitea (now uses `--force`) -[1.0.4]: https://git.sovransystems.com/api/Sovran_Systems/Sovran_SystemsOS/releases/tag/v1.0.4 +### Security +- Hardened Lightning Wallet Connections (NWC): restricted `ReadOnlyPaths` for the unlock password, + fixed an Authorization-header bug, eliminated stack-trace exposure flagged by CodeQL, + and tightened credential access and amount validation + +[1.0.4]: https://git.sovransystems.com/Sovran_Systems/Sovran_SystemsOS/releases/tag/v1.0.4 ## [1.0.3] - 2026-07-29 diff --git a/scripts/release-stable.sh b/scripts/release-stable.sh index 32da184..96e3065 100755 --- a/scripts/release-stable.sh +++ b/scripts/release-stable.sh @@ -130,7 +130,7 @@ done if [[ -z "$RELEASE_MESSAGE" ]]; then echo - read -rp "Enter release message (or press Enter for default): " input_msg + read -rp "Enter release headline (or press Enter for default): " input_msg if [[ -n "$input_msg" ]]; then RELEASE_MESSAGE="$input_msg" else @@ -138,6 +138,91 @@ if [[ -z "$RELEASE_MESSAGE" ]]; then fi fi +# ───────────────────────────────────────────────────────────────────────────── +# Helper: Generate categorized release notes from commit history +# Groups commits since the last tag into Keep-a-Changelog sections based on +# conventional-commit prefixes (feat/fix/docs/security/etc.) and keywords. +# ───────────────────────────────────────────────────────────────────────────── +generate_release_notes() { + local range="$1" + + local added="" changed="" fixed="" security="" docs="" + + while IFS= read -r subject; do + # Skip noise commits + case "$subject" in + "Initial plan"|"initial plan") continue ;; + "Merge pull request"*|"Merge branch"*) continue ;; + "chore: bump VERSION"*|"docs: update CHANGELOG"*) continue ;; + "Address code review"*|"Address review"*|"Address validation"*) continue ;; + esac + + # Strip conventional-commit prefix for display + local clean + clean="$(echo "$subject" | sed -E 's/^(feat|fix|docs|chore|refactor|test|security|perf|style|ci|build)(\([^)]*\))?!?:[[:space:]]*//')" + # Capitalize first letter + clean="$(echo "${clean:0:1}" | tr '[:lower:]' '[:upper:]')${clean:1}" + + case "$subject" in + security:*|security\(*) security+="- ${clean}"$'\n' ;; + feat:*|feat\(*) added+="- ${clean}"$'\n' ;; + fix:*|fix\(*|Fix\ *|fixed\ *) fixed+="- ${clean}"$'\n' ;; + docs:*|docs\(*) docs+="- ${clean}"$'\n' ;; + refactor:*|refactor\(*|chore:*|chore\(*|removed\ *|Updated\ *|updated\ *) changed+="- ${clean}"$'\n' ;; + test:*|test\(*) continue ;; + *) added+="- ${clean}"$'\n' ;; + esac + done < <(git log --no-merges --format='%s' "$range" 2>/dev/null | awk '!seen[$0]++') + + local notes="" + if [[ -n "$added" ]]; then notes+=$'### Added\n'"$added"$'\n'; fi + if [[ -n "$changed" ]]; then notes+=$'### Changed\n'"$changed"$'\n'; fi + if [[ -n "$fixed" ]]; then notes+=$'### Fixed\n'"$fixed"$'\n'; fi + if [[ -n "$security" ]]; then notes+=$'### Security\n'"$security"$'\n'; fi + if [[ -n "$docs" ]]; then notes+=$'### Documentation\n'"$docs"$'\n'; fi + + if [[ -z "$notes" ]]; then + notes=$'### Changed\n- Incremental stable updates\n' + fi + + printf '%s' "$notes" +} + +# Build the notes from commits since the previous tag +if [[ -n "$LATEST_TAG" ]] && git rev-parse -q --verify "$LATEST_TAG" >/dev/null; then + COMMIT_RANGE="${LATEST_TAG}..HEAD" +else + COMMIT_RANGE="HEAD" +fi + +echo +echo -e "${BLUE}Generating draft release notes from ${COMMIT_RANGE}...${NC}" +RELEASE_NOTES="$(generate_release_notes "$COMMIT_RANGE")" + +# Let the user review/edit the generated notes before publishing +NOTES_FILE="$(mktemp "/tmp/release-notes-${TAG}.XXXXXX.md")" +{ + echo "## Sovran_SystemsOS ${TAG}" + echo + echo "${RELEASE_MESSAGE}" + echo + echo "$RELEASE_NOTES" + echo "**Full changelog:** [CHANGELOG.md](https://github.com/naturallaw777/Sovran_SystemsOS/blob/main/CHANGELOG.md)" +} > "$NOTES_FILE" + +echo -e " ${GREEN}✓${NC} Draft notes written to: ${CYAN}${NOTES_FILE}${NC}" +echo +echo "──────────────── Draft Release Notes ────────────────" +cat "$NOTES_FILE" +echo "──────────────────────────────────────────────────────" +echo +read -rp "Edit the notes before publishing? (y/N): " edit_confirm +if [[ "$edit_confirm" =~ ^[Yy]$ ]]; then + "${EDITOR:-nano}" "$NOTES_FILE" + RELEASE_NOTES="$(sed -n '/^###/,$p' "$NOTES_FILE" | sed '/^\*\*Full changelog/d')" +fi +RELEASE_BODY="$(cat "$NOTES_FILE")" + echo echo -e "${YELLOW}════════════════════════════════════════════════════════════${NC}" echo -e "${YELLOW} Preparing Release${NC}" @@ -200,19 +285,11 @@ echo -e "${BLUE}Step 3: Updating ${CHANGELOG_FILE}...${NC}" TODAY=$(date +%Y-%m-%d) -# Create new changelog entry +# Create new changelog entry from the generated notes (no placeholders) NEW_ENTRY="## [${VERSION}] - ${TODAY} -### Added -- (Add new features here) - -### Changed -- (Add changes here) - -### Fixed -- (Add bug fixes here) - -[${VERSION}]: ${GITEA_API_URL%/*}/Sovran_Systems/Sovran_SystemsOS/releases/tag/${TAG} +${RELEASE_NOTES} +[${VERSION}]: https://git.sovransystems.com/Sovran_Systems/Sovran_SystemsOS/releases/tag/${TAG} " # Prepend to changelog (after the header) @@ -281,8 +358,8 @@ echo -e "${BLUE}Step 4: Creating GitHub Release...${NC}" if command -v gh &>/dev/null; then if gh release create "${TAG}" \ --repo naturallaw777/Sovran_SystemsOS \ - --title "${TAG}" \ - --notes "${RELEASE_MESSAGE}" \ + --title "${TAG} — ${RELEASE_MESSAGE#Sovran_SystemsOS v* — }" \ + --notes-file "${NOTES_FILE}" \ --target main 2>/dev/null; then echo -e " ${GREEN}✓${NC} GitHub release created successfully" else @@ -313,16 +390,21 @@ fi if [[ -n "${GITEA_TOKEN:-}" ]]; then GITEA_REPO="Sovran_Systems/Sovran_SystemsOS" + # Build JSON payload safely (release body may contain quotes/newlines) + if command -v jq &>/dev/null; then + PAYLOAD=$(jq -n \ + --arg tag "${TAG}" \ + --arg name "${TAG} — Stable Release" \ + --arg body "${RELEASE_BODY}" \ + '{tag_name: $tag, name: $name, body: $body, draft: false, prerelease: false}') + else + PAYLOAD=$(python3 -c "import json,sys; print(json.dumps({'tag_name': sys.argv[1], 'name': sys.argv[1] + ' — Stable Release', 'body': open(sys.argv[2]).read(), 'draft': False, 'prerelease': False}))" "${TAG}" "${NOTES_FILE}") + fi + RESPONSE=$(curl -s -X POST \ -H "Authorization: token ${GITEA_TOKEN}" \ -H "Content-Type: application/json" \ - -d "{ - \"tag_name\": \"${TAG}\", - \"name\": \"${TAG}\", - \"body\": \"${RELEASE_MESSAGE}\", - \"draft\": false, - \"prerelease\": false - }" \ + -d "${PAYLOAD}" \ "${GITEA_API_URL}/repos/${GITEA_REPO}/releases" 2>/dev/null || echo "") if echo "$RESPONSE" | grep -q '"id"'; then @@ -348,3 +430,6 @@ echo " • Verify releases on both GitHub and Gitea" echo echo -e "${CYAN}Tag created: ${TAG}${NC}" git show "${TAG}" --quiet + +# Clean up temp notes file +rm -f "${NOTES_FILE}"