# vociferate [![Main Validation](https://git.hrafn.xyz/aether/vociferate/actions/workflows/push-validation.yml?branch=main&event=push)](https://git.hrafn.xyz/aether/vociferate/actions/workflows/push-validation.yml) [![Prepare Release](https://git.hrafn.xyz/aether/vociferate/actions/workflows/prepare-release.yml?event=workflow_dispatch)](https://git.hrafn.xyz/aether/vociferate/actions/workflows/prepare-release.yml) [![Do Release](https://git.hrafn.xyz/aether/vociferate/actions/workflows/do-release.yml?event=push)](https://git.hrafn.xyz/aether/vociferate/actions/workflows/do-release.yml) [![Coverage](https://s3.hrafn.xyz/aether-workflow-report-artefacts/vociferate/branch/main/coverage-badge.svg)](https://s3.hrafn.xyz/aether-workflow-report-artefacts/vociferate/branch/main/coverage.html) `vociferate` is an `aether` release orchestration tool written in Go for repositories that want changelog-driven versioning, automated release preparation, and repeatable tag publication. It started as release preparation glue, but it now covers the full release path: recommend the next semantic version, promote `Unreleased` changelog entries, commit and tag a release, and publish release notes/assets from the tagged revision. ## Use In Other Repositories Vociferate ships two composite actions that together cover the full release flow. Pin both to the same released tag. ### `prepare` — update files, commit, and push tag ```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 - uses: git.hrafn.xyz/aether/vociferate/prepare@v1.0.0 with: version: ${{ inputs.version }} publish: needs: prepare uses: aether/vociferate/.gitea/workflows/do-release.yml@main with: tag: ${{ needs.prepare.outputs.version }} secrets: inherit ``` Downloads a prebuilt vociferate binary, runs it to update `changelog.md` and `release-version`, then commits those changes to the default branch and pushes the release tag. Does not require Go on the runner. For repositories that embed the version inside source code, pass `version-file` and `version-pattern`: ```yaml - uses: git.hrafn.xyz/aether/vociferate/prepare@v1.0.0 with: version-file: internal/myapp/version/version.go version-pattern: 'const Version = "([^"]+)"' git-add-files: changelog.md internal/myapp/version/version.go ``` `prepare` uses `github.token` internally for authenticated fetch/push operations, so no token input is required. ### `publish` — create release with changelog notes ```yaml name: Do Release on: workflow_dispatch: inputs: tag: description: Semantic version to publish (for example v1.2.3) required: true jobs: release: uses: aether/vociferate/.gitea/workflows/do-release.yml@main with: tag: ${{ inputs.tag }} secrets: inherit ``` Reads the matching section from `changelog.md` and creates or updates the Gitea/GitHub release with those notes. The `version` input is optional — when omitted it is derived from the current tag ref automatically. The `publish` action outputs `release-id` so you can upload additional release assets after it runs: ```yaml - id: publish uses: git.hrafn.xyz/aether/vociferate/publish@v1.0.0 - name: Upload my binary run: | curl --fail-with-body -X POST \ -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \ -H "Content-Type: application/octet-stream" \ "${{ github.api_url }}/repos/${{ github.repository }}/releases/${{ steps.publish.outputs.release-id }}/assets?name=myapp" \ --data-binary "@dist/myapp" ``` ## Why The Name > **vociferate** _(verb)_: to cry out loudly or forcefully. Long story short: vociferating into the Æther is synonymous screaming into the void. If updating changelogs and documenting releases has ever felt like that, this tool is for you. ## 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` When no `--version-file` flag is provided, `vociferate` derives the current version from the most recent released section heading in the changelog (`## [x.y.z] - ...`). If no prior releases exist, it defaults to `0.0.0` and recommends `v1.0.0` as the first tag. During prepare, vociferate also normalizes changelog heading links when it can determine the repository URL (from CI environment variables or `origin` git remote): - `## [Unreleased]` becomes a link to the repository main branch. - `## [x.y.z] - YYYY-MM-DD` becomes a link to the corresponding release page. If the repository URL cannot be determined, headings remain in plain form. When running `--version`, the `release-version` file is created automatically if it does not exist, so new repositories do not need to pre-seed it. Repositories that keep the version inside source code should pass explicit `--version-file` and `--version-pattern` values; in that case the version file is used directly instead of the changelog. ## 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. - `Prepare Release` then calls `Do Release` directly via reusable `workflow_call` with the resolved tag. - `Do Release` reads the matching changelog section from that tagged revision, creates or updates the release, and uploads prebuilt binaries. Calling `Do Release` directly avoids environments where tag pushes from workflow tokens do not emit a follow-up workflow trigger event. ## 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.