feat: Unified release note management

This commit is contained in:
Jake Turner 2026-02-11 12:39:52 -08:00 committed by Jake Turner
parent 4425e02c3c
commit 4ac261477a
4 changed files with 221 additions and 4 deletions

99
.github/scripts/finalize-release-notes.sh vendored Executable file
View File

@ -0,0 +1,99 @@
#!/usr/bin/env bash
#
# finalize-release-notes.sh
#
# Stamps the "## Unreleased" section in a release-notes file with a version
# and date, and extracts the section content for use in GitHub releases / email.
#
# Usage: finalize-release-notes.sh <version> <file-path>
#
# Exit codes:
# 0 - Success: section stamped and extracted
# 1 - No "## Unreleased" section found (skip gracefully)
# 2 - Unreleased section exists but is empty (skip gracefully)
set -euo pipefail
VERSION="${1:?Usage: finalize-release-notes.sh <version> <file-path>}"
FILE="${2:?Usage: finalize-release-notes.sh <version> <file-path>}"
if [[ ! -f "$FILE" ]]; then
echo "Error: File not found: $FILE" >&2
exit 1
fi
# Find the line number of the ## Unreleased header (case-insensitive)
HEADER_LINE=$(grep -inm1 '^## unreleased' "$FILE" | cut -d: -f1)
if [[ -z "$HEADER_LINE" ]]; then
echo "No '## Unreleased' section found. Skipping."
exit 1
fi
TOTAL_LINES=$(wc -l < "$FILE")
# Find the next section header (## Version ...) or --- separator after the Unreleased header
NEXT_SECTION_LINE=""
if [[ $HEADER_LINE -lt $TOTAL_LINES ]]; then
NEXT_SECTION_LINE=$(tail -n +"$((HEADER_LINE + 1))" "$FILE" \
| grep -nm1 '^## \|^---$' \
| cut -d: -f1)
fi
if [[ -n "$NEXT_SECTION_LINE" ]]; then
# NEXT_SECTION_LINE is relative to HEADER_LINE+1, convert to absolute
END_LINE=$((HEADER_LINE + NEXT_SECTION_LINE - 1))
else
# Section runs to end of file
END_LINE=$TOTAL_LINES
fi
# Extract content between header and next section (exclusive of both boundaries)
CONTENT_START=$((HEADER_LINE + 1))
CONTENT_END=$END_LINE
# Extract the section body (between header line and the next boundary)
SECTION_BODY=$(sed -n "${CONTENT_START},${CONTENT_END}p" "$FILE" | sed '/^$/N;/^\n$/d')
# Check for actual content: strip blank lines and lines that are only markdown headers (###...)
TRIMMED=$(echo "$SECTION_BODY" | sed '/^[[:space:]]*$/d')
HAS_CONTENT=$(echo "$SECTION_BODY" | sed '/^[[:space:]]*$/d' | grep -v '^###' || true)
if [[ -z "$TRIMMED" || -z "$HAS_CONTENT" ]]; then
echo "Unreleased section is empty. Skipping."
exit 2
fi
# Format the date as "Month Day, Year"
DATE_STAMP=$(date +'%B %-d, %Y')
NEW_HEADER="## Version ${VERSION} - ${DATE_STAMP}"
# Build the replacement: swap the header line, keep everything else intact
{
# Lines before the Unreleased header
if [[ $HEADER_LINE -gt 1 ]]; then
head -n "$((HEADER_LINE - 1))" "$FILE"
fi
# New versioned header
echo "$NEW_HEADER"
# Content between header and next section
sed -n "${CONTENT_START},${CONTENT_END}p" "$FILE"
# Rest of the file after the section
if [[ $END_LINE -lt $TOTAL_LINES ]]; then
tail -n +"$((END_LINE + 1))" "$FILE"
fi
} > "${FILE}.tmp"
mv "${FILE}.tmp" "$FILE"
# Write the extracted section content (for GitHub release body / future email)
{
echo "$NEW_HEADER"
echo ""
echo "$TRIMMED"
} > "${FILE}.section"
echo "Finalized release notes for v${VERSION}"
echo " Updated: ${FILE}"
echo " Extracted: ${FILE}.section"
exit 0

View File

@ -35,3 +35,46 @@ jobs:
GIT_AUTHOR_EMAIL: dev@cosmistack.com
GIT_COMMITTER_NAME: cosmistack-bot
GIT_COMMITTER_EMAIL: dev@cosmistack.com
- name: Finalize release notes
if: steps.semver.outputs.new_release_published == 'true'
id: finalize-notes
run: |
git pull origin master
chmod +x .github/scripts/finalize-release-notes.sh
EXIT_CODE=0
.github/scripts/finalize-release-notes.sh \
"${{ steps.semver.outputs.new_release_version }}" \
admin/docs/release-notes.md || EXIT_CODE=$?
if [[ "$EXIT_CODE" -eq 0 ]]; then
echo "has_notes=true" >> $GITHUB_OUTPUT
else
echo "has_notes=false" >> $GITHUB_OUTPUT
fi
- name: Commit finalized release notes
if: steps.semver.outputs.new_release_published == 'true' && steps.finalize-notes.outputs.has_notes == 'true'
run: |
git config user.name "cosmistack-bot"
git config user.email "dev@cosmistack.com"
git remote set-url origin https://x-access-token:${{ secrets.COSMISTACKBOT_ACCESS_TOKEN }}@github.com/${{ github.repository }}.git
git add admin/docs/release-notes.md
git commit -m "docs(release): finalize v${{ steps.semver.outputs.new_release_version }} release notes [skip ci]"
git push origin master
- name: Update GitHub release body
if: steps.semver.outputs.new_release_published == 'true' && steps.finalize-notes.outputs.has_notes == 'true'
env:
GH_TOKEN: ${{ secrets.COSMISTACKBOT_ACCESS_TOKEN }}
run: |
gh release edit "v${{ steps.semver.outputs.new_release_version }}" \
--notes-file admin/docs/release-notes.md.section
# Future: Send release notes email
# - name: Send release notes email
# if: steps.semver.outputs.new_release_published == 'true' && steps.finalize-notes.outputs.has_notes == 'true'
# run: |
# curl -X POST "https://api.projectnomad.us/api/v1/newsletter/release" \
# -H "Authorization: Bearer ${{ secrets.NOMAD_API_KEY }}" \
# -H "Content-Type: application/json" \
# -d "{\"version\": \"${{ steps.semver.outputs.new_release_version }}\", \"body\": $(cat admin/docs/release-notes.md.section | jq -Rs .)}"

View File

@ -92,10 +92,43 @@ To test internet connectivity, N.O.M.A.D. attempts to make a request to Cloudfla
## About Security
By design, Project N.O.M.A.D. is intended to be open and available without hurdles - it includes no authentication. If you decide to connect your device to a local network after install (e.g. for allowing other devices to access it's resources), you can block/open ports to control which services are exposed.
## Versioning
**Will authentication be added in the future?** Maybe. It's not currently a priority, but if there's enough demand for it, we may consider building in an optional authentication layer in a future release to support uses cases where multiple users need access to the same instance but with different permission levels (e.g. family use with parental controls, classroom use with teacher/admin accounts, etc.). For now, we recommend using network-level controls to manage access if you're planning to expose your N.O.M.A.D. instance to other devices on a local network. N.O.M.A.D. is not designed to be exposed directly to the internet, and we strongly advise against doing so unless you really know what you're doing, have taken appropriate security measures, and understand the risks involved.
## Contributing
Contributions are welcome and appreciated! Please read this section fully to understand how to contribute to the project.
### General Guidelines
- **Open an issue first**: Before starting work on a new feature or bug fix, please open an issue to discuss your proposed changes. This helps ensure that your contribution aligns with the project's goals and avoids duplicate work. Title the issue clearly and provide a detailed description of the problem or feature you want to work on.
- **Fork the repository**: Click the "Fork" button at the top right of the repository page to create a copy of the project under your GitHub account.
- **Create a new branch**: In your forked repository, create a new branch for your work. Use a descriptive name for the branch that reflects the purpose of your changes (e.g., `fix/issue-123` or `feature/add-new-tool`).
- **Make your changes**: Implement your changes in the new branch. Follow the existing code style and conventions used in the project. Be sure to test your changes locally to ensure they work as expected.
- **Add Release Notes**: If your changes include new features, bug fixes, or improvements, please see the "Release Notes" section below to properly document your contribution for the next release.
- **Conventional Commits**: When committing your changes, please use conventional commit messages to provide clear and consistent commit history. The format is `<type>(<scope>): <description>`, where:
- `type` is the type of change (e.g., `feat` for new features, `fix` for bug fixes, `docs` for documentation changes, etc.)
- `scope` is an optional area of the codebase that your change affects (e.g., `api`, `ui`, `docs`, etc.)
- `description` is a brief summary of the change
- **Submit a pull request**: Once your changes are ready, submit a pull request to the main repository. Provide a clear description of your changes and reference any related issues. The project maintainers will review your pull request and may provide feedback or request changes before it can be merged.
- **Be responsive to feedback**: If the maintainers request changes or provide feedback on your pull request, please respond in a timely manner. Stale pull requests may be closed if there is no activity for an extended period.
- **Follow the project's code of conduct**: Please adhere to the project's code of conduct when interacting with maintainers and other contributors. Be respectful and considerate in your communications.
- **No guarantee of acceptance**: The project is community-driven, and all contributions are appreciated, but acceptance is not guaranteed. The maintainers will evaluate each contribution based on its quality, relevance, and alignment with the project's goals.
- **Thank you for contributing to Project N.O.M.A.D.!** Your efforts help make this project better for everyone.
### Versioning
This project uses semantic versioning. The version is managed in the root `package.json`
and automatically updated by semantic-release. For simplicity's sake, the "project-nomad" container
uses the same version defined there instead of the version in `admin/package.json` (stays at 0.0.0), as it's the only container derived from the code.
and automatically updated by semantic-release. For simplicity's sake, the "project-nomad" image
uses the same version defined there instead of the version in `admin/package.json` (stays at 0.0.0), as it's the only published image derived from the code.
### Release Notes
Human-readable release notes live in [`admin/docs/release-notes.md`](admin/docs/release-notes.md) and are displayed in the Command Center's built-in documentation.
When working on changes, add a summary to the `## Unreleased` section at the top of that file under the appropriate heading:
- **Features** — new user-facing capabilities
- **Bug Fixes** — corrections to existing behavior
- **Improvements** — enhancements, refactors, docs, or dependency updates
Use the format `- **Area**: Description` to stay consistent with existing entries. When a release is triggered, CI automatically stamps the version and date, commits the update, and pushes the content to the GitHub release.
## Community & Resources

View File

@ -1,5 +1,47 @@
# Release Notes
## Unreleased
### Features
### Bug Fixes
### Improvements
---
## Version 1.24.0 - February 10, 2026
### 🚀 Features
- **AI Assistant**: Query rewriting for enhanced context retrieval
- **AI Assistant**: Allow manual scan and resync of Knowledge Base
- **AI Assistant**: Integrated Knowledge Base UI into AI Assistant page
- **AI Assistant**: ZIM content embedding into Knowledge Base
- **Downloads**: Display model download progress
- **System**: Cron job for automatic update checks
- **Docs**: Polished documentation rendering with desert-themed components
### 🐛 Bug Fixes
- **AI Assistant**: Chat suggestion performance improvements
- **AI Assistant**: Inline code rendering
- **GPU**: Detect NVIDIA GPUs via Docker API instead of lspci
- **Install**: Improve Docker GPU configuration
- **System**: Correct memory usage percentage calculation
- **System**: Show host OS, hostname, and GPU instead of container info
- **Collections**: Correct devdocs ZIM filenames in Computing & Technology
- **Downloads**: Sort active downloads by progress descending
- **Docs**: Fix multiple broken internal links and route references
### ✨ Improvements
- **Docs**: Overhauled in-app documentation with sidebar ordering
- **Docs**: Updated README with feature overview
- **GPU**: Reusable utility for running nvidia-smi
---
## Version 1.23.0 - February 5, 2026
### 🚀 Features