diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 0000000..2a4138c --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,43 @@ + + +## Summary + + + +## Related Issues + + + +Refs # + +## Changes + + + +- +- +- + +## Further Comments + + diff --git a/.github/release.yml b/.github/release.yml new file mode 100644 index 0000000..2e14d4e --- /dev/null +++ b/.github/release.yml @@ -0,0 +1,38 @@ +changelog: + exclude: + labels: + - duplicate + - good-first-issue + - help-wanted + - invalid + - question + - wont-fix + + categories: + - title: "Breaking Changes" + labels: + - breaking-change + + - title: "Security" + labels: + - security + + - title: "Enhancements" + labels: + - enhancement + + - title: "Bug Fixes" + labels: + - bug + + - title: "Documentation" + labels: + - documentation + + - title: "Dependencies" + labels: + - dependencies + + - title: "Other Changes" + labels: + - "*" diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 8562016..e904fa0 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -118,22 +118,24 @@ jobs: exit 1 fi - # Compute checksums from inside dist/ so the paths in checksums.txt don't include the dist/ prefix. - (cd dist && sha256sum $files) | sort > checksums.txt + # Compute checksums: format is "filename checksum" (filename first, stripped of artifact directory) + (cd dist && sha256sum $files) | while read sum file; do + echo "$(basename "$file") $sum" + done | sort > checksums.txt echo "" echo "checksums.txt:" cat checksums.txt - - name: Prepare release notes + - name: Prepare checksums body shell: bash run: | set -euo pipefail { - echo "Automated release for v${{ needs.validate.outputs.version }}." echo "" - echo "SHA256 checksums:" + echo "## SHA256 Checksums" + echo "" echo '```' cat checksums.txt echo '```' @@ -147,6 +149,8 @@ jobs: uses: softprops/action-gh-release@v2 with: name: "keystone-cli v${{ needs.validate.outputs.version }}" + generate_release_notes: true + append_body: true body_path: release-body.md files: | dist/**/keystone-cli_${{ needs.validate.outputs.version }}_*.tar.gz diff --git a/CLAUDE.md b/CLAUDE.md index 3fea5c4..028e81b 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -27,8 +27,20 @@ keystone-cli/ ├── tests/ │ └── Keystone.Cli.UnitTests/ # Unit tests mirroring src structure ├── docs/ +│ ├── how-to/ # Procedural guides +│ │ ├── how-to-release.md # Release process documentation +│ │ ├── how-to-test-man-page.md # Man page testing guide +│ │ └── how-to-workflow.md # Development workflow guide │ └── man/ # Manual pages in mdoc format +├── .github/ +│ ├── workflows/ # GitHub Actions +│ │ ├── ci.yml # CI pipeline (tests on PR/push) +│ │ ├── release.yml # Release build and publish +│ │ └── tag-release.yml # Manual tag creation workflow +│ ├── pull_request_template.md # PR template +│ └── release.yml # Release notes configuration ├── scripts/ # Build and utility scripts +│ └── package-release.sh # Tarball packaging script ├── artifacts/ # Build outputs ├── Directory.Build.props # MSBuild configuration └── keystone-cli.sln # Visual Studio solution @@ -164,3 +176,32 @@ Tests mirror the source structure in `tests/Keystone.Cli.UnitTests/`: - Self-contained single-file publishing enabled - Deterministic builds for CI/CD - Centralized build outputs in `artifacts/` directory + +## CI/CD and Release Process + +### GitHub Workflows + +- **ci.yml**: Runs unit tests on PRs and pushes to main +- **tag-release.yml**: Manual workflow to create a version tag from csproj version +- **release.yml**: Triggered by `v*.*.*` tags; validates version, builds multi-platform + binaries, generates checksums, and publishes GitHub Release + +### Release Flow + +1. Update version using `/version X.Y.Z` command (updates csproj, man page, and tests) +2. Create PR and merge to main +3. Run `tag-release.yml` workflow manually (creates and pushes tag) +4. `release.yml` triggers automatically on tag push +5. Release published with binaries for osx-arm64, osx-x64, linux-x64, linux-arm64, etc. + +### GitHub Configuration + +- **release.yml** (in `.github/`): Configures auto-generated release notes categories + (Breaking Changes, Security, Enhancements, Bug Fixes, Documentation, Dependencies) +- **pull_request_template.md**: PR template enforcing outcome-focused descriptions and + label requirements + +### Scripts + +- **package-release.sh**: Creates release tarballs with binary, config, and man page; + generates SHA256 checksums. Usage: `./scripts/package-release.sh [version] [rid]` diff --git a/README.md b/README.md index 4066bd4..aec8487 100644 --- a/README.md +++ b/README.md @@ -44,39 +44,12 @@ man keystone-cli The project is organized into four main parts: -- [docs](docs) – Contains documentation files, including man pages in [mdoc(7)](https://man.openbsd.org/mdoc.7) +- [docs](docs) – Contains how-tos, documentation files, including man pages in [mdoc(7)](https://man.openbsd.org/mdoc.7) format and other relevant documentation. - [scripts](scripts) – Build and utility scripts. - [src](src) – Application source code. - [tests](tests) – Unit tests organized to mirror the structure of the application for consistency and coverage. -## Testing the Man Page - -All examples assume you're in the root directory of the project. - -Man pages use the [mdoc(7)](https://man.openbsd.org/mdoc.7) format -- a semantic markup language designed specifically -for writing Unix manual pages. While the `man` command can be used to view them, the `mandoc` utility is preferred for -local testing and rendering. - -To read the [mdoc(7)](https://man.openbsd.org/mdoc.7) documentation in your terminal: - -```bash -man 7 mdoc -``` - -### Using `mandoc` - -To test the generated man page locally: - -```bash -mandoc docs/man/man1/keystone-cli.1 -``` - -### Using `man` - -To view the man page with man, you must supply an absolute path for the man path: - -```bash -man -M "$(cd docs/man && pwd)" keystone-cli -``` +Review the contents of [docs/how-to](docs/how-to) for detailed guides on working with the project, contributing, +and releasing new versions. diff --git a/docs/RELEASE.md b/docs/how-to/how-to-release.md similarity index 100% rename from docs/RELEASE.md rename to docs/how-to/how-to-release.md diff --git a/docs/how-to/how-to-test-man-page.md b/docs/how-to/how-to-test-man-page.md new file mode 100644 index 0000000..fd1c7da --- /dev/null +++ b/docs/how-to/how-to-test-man-page.md @@ -0,0 +1,29 @@ +# Testing the Man Page + +All examples assume you're in the root directory of the project. + +Man pages use the [mdoc(7)](https://man.openbsd.org/mdoc.7) format -- a semantic markup language designed specifically +for writing Unix manual pages. While the `man` command can be used to view them, the `mandoc` utility is preferred for +local testing and rendering. + +To read the [mdoc(7)](https://man.openbsd.org/mdoc.7) documentation in your terminal: + +```bash +man 7 mdoc +``` + +### Using `mandoc` + +To test the generated man page locally: + +```bash +mandoc docs/man/man1/keystone-cli.1 +``` + +### Using `man` + +To view the man page with man, you must supply an absolute path for the man path: + +```bash +man -M "$(cd docs/man && pwd)" keystone-cli +``` diff --git a/docs/how-to/how-to-workflow.md b/docs/how-to/how-to-workflow.md new file mode 100644 index 0000000..a035391 --- /dev/null +++ b/docs/how-to/how-to-workflow.md @@ -0,0 +1,68 @@ +# Workflow + +This document outlines the project workflow. It describes the main steps and tasks required to ensure a smooth +and efficient process. + +## Issue and Change Tracking Workflow + +This project uses GitHub Issues and Pull Requests to track work and generate meaningful release notes with minimal +overhead. GitHub's default labels are used and intentionally kept unchanged. + +### 1. Creating an Issue (Ticket) + +Create a GitHub Issue for any user-visible change, bug, or non-trivial refactor worth tracking. + +- Use a clear, outcome-focused title +- Add a short description explaining the problem or goal +- Apply one or more of GitHub's predefined labels as appropriate: + - `bug` – something is broken + - `enhancement` – new feature or improvement + - `documentation` – docs-related changes + - `question` – clarification or discussion + +Issues act as lightweight tickets and historical context. + +### 2. Working on an Issue + +- Create a branch for the work (naming is flexible but should be descriptive) +- Implement the change +- Commit freely during development + +Branch naming is optional and does not affect automation. + +### 3. Opening a Pull Request + +Open a Pull Request when the work is ready for review or merge. + +- The PR title **must be release-note quality** (it will appear verbatim in release notes) +- The PR description should reference the issue using one of the following: + - `Fixes #` – closes the issue when merged + - `Refs #` – links the issue without closing it + +Apply the same predefined label(s) used on the issue to the Pull Request. + +### 4. Merging + +- Prefer **squash merges** to keep history and release notes clean +- Ensure all required checks pass +- Avoid direct commits to the main branch + +The merged PR title becomes the primary entry in the next release notes. + +### 5. Releasing + +For more information, see [How to release](how-to-release.md). + +- When ready to ship, run the **Tag release** workflow manually +- This workflow creates a version tag +- Pushing the tag automatically triggers the Release workflow + +Release notes are generated automatically from merged Pull Requests since the previous tag. + +### 6. Release Notes Generation + +- Release notes are PR-first and grouped by labels +- Only merged Pull Requests are included +- Issues are linked via PR references (no manual curation required) + +This keeps releases fully automated while preserving traceability and clarity.