From 62c92eb650919db810c3e75b65f217ef2b338b14 Mon Sep 17 00:00:00 2001 From: Dustin Hilgaertner Date: Sun, 5 Apr 2026 15:34:11 -0500 Subject: [PATCH] Add CHANGELOG.md and adopt semantic versioning Establish a versioning strategy with a single source of truth (VERSION file) and a changelog following Keep a Changelog format, backfilled from git history as the 0.1.0 release. - Create VERSION file (0.1.0) as the canonical version source - Update generate-build-info.sh to read VERSION and generate both BuildInfo.swift (with version + build number) and CLIVersion.swift - Update bundle.sh to inject version and git-derived build number into Info.plist dynamically instead of hardcoding - Update CrowCLI to use generated CLIVersion instead of hardcoded string - Create CHANGELOG.md with backfilled 0.1.0 release notes - Document versioning strategy and release process in CONTRIBUTING.md Closes #62 Co-Authored-By: Claude Opus 4.6 (1M context) --- .gitignore | 1 + CHANGELOG.md | 42 ++++++++++++++++++++++++++++++++++ CONTRIBUTING.md | 30 ++++++++++++++++++++++++ Sources/CrowCLI/CrowCLI.swift | 2 +- VERSION | 1 + scripts/bundle.sh | 25 ++++++++++++++++---- scripts/generate-build-info.sh | 35 +++++++++++++++++++++++----- 7 files changed, 125 insertions(+), 11 deletions(-) create mode 100644 CHANGELOG.md create mode 100644 VERSION diff --git a/.gitignore b/.gitignore index 421b9a1..d7bd74c 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,7 @@ xcuserdata/ # Generated sources Sources/Crow/Generated/ +Sources/CrowCLI/Generated/ # App bundle *.app diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..9ca9481 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,42 @@ +# Changelog + +All notable changes to Crow will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [Unreleased] + +## [0.1.0] - 2025-04-05 + +Initial open-source release of Crow. + +### Added + +- Native macOS application with ticket board, terminal management, and GitHub integration +- Embedded Ghostty terminal with multi-tab support per session +- Session-based workflow management (create, pause, resume, archive) +- Git worktree management with orphan worktree recovery +- GitHub integration with PR status tracking and project board sync +- "In Review" button to update GitHub Project status from the app +- Claude Code hook event system for automatic session activity tracking +- Notification system with configurable sounds and macOS notifications +- "Open in VS Code" and "Open Terminal" buttons for session worktrees +- CLI tool (`crow`) for session, terminal, and metadata management via Unix socket RPC +- `crow setup` command for first-time configuration +- Makefile for build automation (`make build`, `make release`) +- Corveil branding with styled About page showing git commit SHA +- Configurable sidebar with option to hide subtitle lines +- Ticket page redesign with search, sort, and done state filtering +- Claude Code allow list aggregation and promotion across worktrees +- Comprehensive README with setup guide, architecture docs, and CLI reference +- Contributing guide, issue templates, and PR template +- Security audit and open-source readiness documentation + +### Fixed + +- Ghostty terminal mouse position offset +- UI blocking during GitHub polling and terminal resize on display change +- Merged PR status not detected on app restart +- Crash when reopening About or Settings window +- Disconnected hooks for CLI-created sessions diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index f2bb539..af6644c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -69,6 +69,36 @@ If a new package is needed, create it under `Packages/` and add it to the root ` - A link to the related issue - Screenshots for UI changes +## Versioning + +Crow follows [Semantic Versioning](https://semver.org/): + +- **Major** (X.0.0) — breaking changes to the CLI, IPC protocol, or config format +- **Minor** (0.X.0) — new features and capabilities +- **Patch** (0.0.X) — bug fixes and minor improvements + +### Version source of truth + +The `VERSION` file at the repo root contains the current version (e.g., `0.1.0`). All build scripts read from this file. Never hardcode a version string elsewhere. + +For CI, set the `CROW_VERSION` environment variable to override the file. The build number (`CFBundleVersion`) is derived automatically from `git rev-list --count HEAD`. + +### Releasing a new version + +1. Update `VERSION` with the new version number +2. Move entries from `[Unreleased]` in `CHANGELOG.md` into a new version section +3. Commit: `git commit -am "Release vX.Y.Z"` +4. Tag: `git tag vX.Y.Z` +5. Push: `git push origin main --tags` + +### Changelog contributions + +When submitting a PR, add a bullet under the `[Unreleased]` section of `CHANGELOG.md` describing your change. Use the categories from [Keep a Changelog](https://keepachangelog.com/): Added, Changed, Deprecated, Removed, Fixed, Security. + +### Future considerations + +We may adopt [Conventional Commits](https://www.conventionalcommits.org/) and automated changelog generation (e.g., [git-cliff](https://git-cliff.org/)) as the project matures. For now, the changelog is maintained manually. + ## Auto-Scaffolded Files Crow auto-generates certain files into `{devRoot}/.claude/` on launch (see `Scaffolder.swift`): diff --git a/Sources/CrowCLI/CrowCLI.swift b/Sources/CrowCLI/CrowCLI.swift index d5e8f54..73a5f5d 100644 --- a/Sources/CrowCLI/CrowCLI.swift +++ b/Sources/CrowCLI/CrowCLI.swift @@ -7,7 +7,7 @@ struct Crow: ParsableCommand { static let configuration = CommandConfiguration( commandName: "crow", abstract: "CLI for Crow — manage sessions, terminals, and metadata", - version: "0.1.0", + version: CLIVersion.version, subcommands: [ Setup.self, NewSession.self, diff --git a/VERSION b/VERSION new file mode 100644 index 0000000..6e8bf73 --- /dev/null +++ b/VERSION @@ -0,0 +1 @@ +0.1.0 diff --git a/scripts/bundle.sh b/scripts/bundle.sh index e908c20..06dfd0f 100755 --- a/scripts/bundle.sh +++ b/scripts/bundle.sh @@ -8,6 +8,23 @@ BUILD_DIR="$ROOT_DIR/.build/release" APP_DIR="$ROOT_DIR/Crow.app" FRAMEWORKS_DIR="$ROOT_DIR/Frameworks" +# Read version: CROW_VERSION env var takes precedence, then VERSION file +if [ -n "${CROW_VERSION:-}" ]; then + VERSION="$CROW_VERSION" +elif [ -f "$ROOT_DIR/VERSION" ]; then + VERSION="$(tr -d '[:space:]' < "$ROOT_DIR/VERSION")" +else + echo "ERROR: No VERSION file found and CROW_VERSION not set" >&2 + exit 1 +fi + +# Build number from git commit count +if git -C "$ROOT_DIR" rev-parse HEAD >/dev/null 2>&1; then + BUILD_NUMBER=$(git -C "$ROOT_DIR" rev-list --count HEAD) +else + BUILD_NUMBER="1" +fi + echo "==> Generating build info..." bash "$SCRIPT_DIR/generate-build-info.sh" @@ -30,7 +47,7 @@ if [ -d "$FRAMEWORKS_DIR/ghostty-resources" ]; then fi # Create Info.plist -cat > "$APP_DIR/Contents/Info.plist" << 'PLIST' +cat > "$APP_DIR/Contents/Info.plist" << PLIST @@ -44,9 +61,9 @@ cat > "$APP_DIR/Contents/Info.plist" << 'PLIST' CFBundleDisplayName Crow CFBundleVersion - 1 + $BUILD_NUMBER CFBundleShortVersionString - 0.1.0 + $VERSION CFBundlePackageType APPL LSMinimumSystemVersion @@ -59,4 +76,4 @@ cat > "$APP_DIR/Contents/Info.plist" << 'PLIST' PLIST -echo "==> App bundle created at: $APP_DIR" +echo "==> App bundle created at: $APP_DIR (version: $VERSION, build: $BUILD_NUMBER)" diff --git a/scripts/generate-build-info.sh b/scripts/generate-build-info.sh index ad9dc7a..5b80b35 100755 --- a/scripts/generate-build-info.sh +++ b/scripts/generate-build-info.sh @@ -1,32 +1,55 @@ #!/usr/bin/env bash -# Generate BuildInfo.swift with git SHA and build date +# Generate BuildInfo.swift and CLIVersion.swift with version, git SHA, and build date set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" ROOT_DIR="$(dirname "$SCRIPT_DIR")" -OUTPUT_DIR="$ROOT_DIR/Sources/Crow/Generated" -OUTPUT_FILE="$OUTPUT_DIR/BuildInfo.swift" +APP_OUTPUT_DIR="$ROOT_DIR/Sources/Crow/Generated" +CLI_OUTPUT_DIR="$ROOT_DIR/Sources/CrowCLI/Generated" -mkdir -p "$OUTPUT_DIR" +mkdir -p "$APP_OUTPUT_DIR" "$CLI_OUTPUT_DIR" + +# Read version: CROW_VERSION env var takes precedence, then VERSION file +if [ -n "${CROW_VERSION:-}" ]; then + VERSION="$CROW_VERSION" +elif [ -f "$ROOT_DIR/VERSION" ]; then + VERSION="$(tr -d '[:space:]' < "$ROOT_DIR/VERSION")" +else + echo "ERROR: No VERSION file found and CROW_VERSION not set" >&2 + exit 1 +fi # Capture git info (fallback to "dev" if not in a git repo) if git -C "$ROOT_DIR" rev-parse HEAD >/dev/null 2>&1; then GIT_SHA=$(git -C "$ROOT_DIR" rev-parse HEAD) GIT_SHORT_SHA=$(git -C "$ROOT_DIR" rev-parse --short HEAD) + BUILD_NUMBER=$(git -C "$ROOT_DIR" rev-list --count HEAD) else GIT_SHA="dev" GIT_SHORT_SHA="dev" + BUILD_NUMBER="1" fi BUILD_DATE=$(date -u +"%Y-%m-%d") -cat > "$OUTPUT_FILE" << EOF +# Generate BuildInfo.swift for the GUI app +cat > "$APP_OUTPUT_DIR/BuildInfo.swift" << EOF // Auto-generated by scripts/generate-build-info.sh — do not edit enum BuildInfo { + static let version = "$VERSION" + static let buildNumber = "$BUILD_NUMBER" static let gitCommitSHA = "$GIT_SHA" static let gitCommitShortSHA = "$GIT_SHORT_SHA" static let buildDate = "$BUILD_DATE" } EOF -echo "Generated $OUTPUT_FILE (SHA: $GIT_SHORT_SHA, date: $BUILD_DATE)" +# Generate CLIVersion.swift for the CLI tool +cat > "$CLI_OUTPUT_DIR/CLIVersion.swift" << EOF +// Auto-generated by scripts/generate-build-info.sh — do not edit +enum CLIVersion { + static let version = "$VERSION" +} +EOF + +echo "Generated build info (version: $VERSION, build: $BUILD_NUMBER, SHA: $GIT_SHORT_SHA, date: $BUILD_DATE)"