diff --git a/.github/release.yml b/.github/release.yml new file mode 100644 index 0000000..7fa5a53 --- /dev/null +++ b/.github/release.yml @@ -0,0 +1,29 @@ +changelog: + exclude: + labels: + - ignore-for-release + authors: + - github-actions[bot] + - dependabot[bot] + categories: + - title: Breaking Changes + labels: + - breaking-change + - Semver-Major + - title: Features + labels: + - enhancement + - feature + - Semver-Minor + - title: Fixes + labels: + - bug + - fix + - title: Maintenance + labels: + - chore + - dependencies + - documentation + - title: Other Changes + labels: + - "*" diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 269c201..18eadb1 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -103,10 +103,64 @@ jobs: permissions: contents: write steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: Resolve release notes range + id: release-target + shell: bash + run: | + set -euo pipefail + tag="${GITHUB_REF_NAME}" + tool="" + version="" + for dir in cmd/*/; do + candidate="$(basename "${dir}")" + if [[ "${tag}" == "${candidate}-v"* ]]; then + tool="${candidate}" + version="${tag#${candidate}-}" + break + fi + done + if [[ -z "${tool}" || -z "${version}" ]]; then + echo "release tag must match a known cmd/ binary, e.g. slack-post-v0.1.0" >&2 + exit 1 + fi + expected="$(make print-tag TOOL="${tool}" VERSION="${version}")" + if [[ "${tag}" != "${expected}" ]]; then + echo "release tag ${tag} does not match normalized tag ${expected}" >&2 + exit 1 + fi + previous_tag="$( + git tag -l "${tool}-v*" --sort=version:refname | + awk -v current="${tag}" '$0 == current { print previous; exit } { previous=$0 }' + )" + echo "tag_name=${tag}" >> "${GITHUB_OUTPUT}" + echo "tool=${tool}" >> "${GITHUB_OUTPUT}" + echo "version=${version}" >> "${GITHUB_OUTPUT}" + echo "previous_tag=${previous_tag}" >> "${GITHUB_OUTPUT}" - uses: actions/download-artifact@v4 with: path: dist merge-multiple: true - - uses: softprops/action-gh-release@v2 + - name: Publish release with generated notes + if: steps.release-target.outputs.previous_tag != '' + uses: softprops/action-gh-release@v2 + with: + name: ${{ steps.release-target.outputs.tag_name }} + body: | + Automated release for `${{ steps.release-target.outputs.tool }}` `${{ steps.release-target.outputs.version }}`. + generate_release_notes: true + previous_tag: ${{ steps.release-target.outputs.previous_tag }} + files: dist/*.tar.gz + fail_on_unmatched_files: true + - name: Publish initial release with generated notes + if: steps.release-target.outputs.previous_tag == '' + uses: softprops/action-gh-release@v2 with: + name: ${{ steps.release-target.outputs.tag_name }} + body: | + Automated release for `${{ steps.release-target.outputs.tool }}` `${{ steps.release-target.outputs.version }}`. + generate_release_notes: true files: dist/*.tar.gz + fail_on_unmatched_files: true diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..f73fb83 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,11 @@ +# Changelog + +All notable changes to Agent CLI Tools are published in GitHub Releases. + +The release workflow generates release notes automatically whenever a per-binary tag is pushed. It compares each release against the previous tag for the same tool, so a `slack-post-v0.2.0` release is compared with the prior `slack-post-v*` tag instead of a tag for another binary. + +Release note categories are configured in [.github/release.yml](.github/release.yml). + +## Releases + +- [slack-post-v0.1.0](https://github.com/berrydev-ai/agent-cli-tools/releases/tag/slack-post-v0.1.0) - Initial `slack-post` release. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..5da3170 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,41 @@ +# Contributing + +Thanks for contributing to Agent CLI Tools. + +## Development + +1. Add each CLI under `cmd/`. +2. Keep tool behavior in focused packages under `internal/cli/`. +3. Support flags and environment variables for required inputs. +4. Add or update command tests for behavior changes. +5. Update the tool README and `.env.example` when inputs, output, or usage changes. + +Run tests before opening a pull request: + +```bash +make test +make build +``` + +## Releases + +Each binary is released independently with a per-binary SemVer tag: + +```text +-v.. +``` + +Use the Makefile targets so validation, archive names, and tags stay consistent: + +```bash +make print-tag TOOL=slack-post VERSION=v0.1.0 +make release-archives TOOL=slack-post VERSION=v0.1.0 +make tag TOOL=slack-post VERSION=v0.1.0 +make push-tag TOOL=slack-post VERSION=v0.1.0 +``` + +Pushing the tag runs the release workflow, publishes platform archives, and generates release notes from merged pull requests and commits. Release note categories are configured in `.github/release.yml`. + +## License + +By contributing, you agree that your contributions are licensed under the MIT License. diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..925f2fb --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 BerryDev AI + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md index 0f8f16b..d8a08d1 100644 --- a/README.md +++ b/README.md @@ -46,6 +46,12 @@ Binaries are written to `dist/`. make test ``` +## Project Docs + +- [Changelog](CHANGELOG.md) +- [Contributing](CONTRIBUTING.md) +- [License](LICENSE) + ## Tool Docs Each binary owns a README in its command path: @@ -77,6 +83,8 @@ make push-tag TOOL=slack-post VERSION=v0.1.0 Pushing a `*-v*` tag that matches a known `cmd/` binary runs `.github/workflows/release.yml`, builds that one binary for Linux and macOS on `amd64` and `arm64`, and publishes tarballs to the GitHub release. +Release notes are generated automatically from merged pull requests and commits, categorized by [.github/release.yml](.github/release.yml), and compared against the previous tag for the same binary. + For example, a tag `slack-post-v0.1.0` produces: ```text