# vociferate A reusable release preparation tool for Go repositories. ## Build Build with just: ```bash just go-build ``` Or directly with Go: ```bash go build -o dist/vociferate ./cmd/vociferate ``` ## Usage Prepare release files: ```bash go run ./cmd/vociferate --version v1.2.3 --date 2026-03-20 --root . ``` In the provided workflow and composite action, `version` is optional. When it is omitted, vociferate computes and uses the recommended next version automatically. Recommend next release tag from changelog content: ```bash go run ./cmd/vociferate --recommend --root . ``` ### Flags - `--version` semantic version to release (with or without leading `v`). - `--date` release date in `YYYY-MM-DD` format. - `--recommend` print recommended next tag based on `## [Unreleased]`. - `--root` repository root directory. - `--version-file` path to version source file relative to `--root`. - `--version-pattern` regexp with exactly one capture group for version value. - `--changelog` path to changelog file relative to `--root`. Defaults: - `version-file`: `release-version` - `version-pattern`: `^\s*([^\r\n]+)\s*$` - `changelog`: `changelog.md` By default, `vociferate` reads and writes the release version as the sole content of a root-level `release-version` file. Repositories that keep the version inside source code should pass explicit `version-file` and `version-pattern` values. ## Testing ```bash just go-test ``` ## Release Flow Releases use two workflows: - `Prepare Release` runs on demand, updates `release-version` and `changelog.md`, commits those changes back to `main`, and pushes the release tag. - `Do Release` runs from the pushed tag, reads the matching changelog section from that tagged revision, creates or updates the release, and uploads prebuilt binaries. This split matters because release notes must be generated from the tagged commit that already contains the promoted changelog section. ## Release Artifacts The tag-driven `Do Release` workflow publishes prebuilt `vociferate` binaries for: - `linux/amd64` - `linux/arm64` It also uploads `checksums.txt` for integrity verification. If a release already exists for the same tag, the workflow updates its release notes and replaces matching asset filenames so reruns stay in sync. ## Reuse In Other Repositories You can reuse vociferate in two ways. Use the composite action directly in your prepare workflow: ```yaml - name: Prepare release files uses: git.hrafn.xyz/aether/vociferate@v1.0.0 with: version-file: internal/myapp/version/version.go version-pattern: 'const Version = "([^"]+)"' changelog: changelog.md ``` Set `version` only when you want to override the recommended version. Pin the composite action to a released tag. It downloads a prebuilt Linux binary from vociferate releases and caches it on the runner, so it does not require installing Go. If your repository uses the default plain-text `release-version` file, you can omit `version-file` and `version-pattern` entirely. A complete release setup should also split preparation from publication. For example: ```yaml name: Prepare Release on: workflow_dispatch: inputs: version: description: Optional semantic version override. required: false jobs: prepare: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: fetch-depth: 0 - name: Prepare release files id: prepare uses: git.hrafn.xyz/aether/vociferate@v1.0.0 with: version: ${{ inputs.version }} - name: Commit and push prepared release run: | set -euo pipefail tag="${{ steps.prepare.outputs.version }}" git config user.name "gitea-actions[bot]" git config user.email "gitea-actions[bot]@users.noreply.local" git add changelog.md release-version git commit -m "release: prepare ${tag}" git tag "$tag" git push origin HEAD git push origin "$tag" ``` Then use a separate tag workflow to publish the release from the tagged revision: ```yaml name: Do Release on: push: tags: - "v*.*.*" jobs: release: uses: aether/vociferate/.gitea/workflows/do-release.yml@main secrets: inherit ``` Call the reusable prepare workflow: ```yaml name: Prepare Release on: workflow_dispatch: inputs: version: description: Optional semantic version override. required: false jobs: release: uses: aether/vociferate/.gitea/workflows/prepare-release.yml@main with: version: ${{ inputs.version }} secrets: inherit ``` And publish from tags with: ```yaml name: Do Release on: push: tags: - "v*.*.*" jobs: release: uses: aether/vociferate/.gitea/workflows/do-release.yml@main secrets: inherit ```