Compare commits
33 Commits
72abf37b2d
...
v1.1.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f82dace4b2 | ||
|
|
81dced6ada | ||
|
|
62693935d0 | ||
|
|
c0b5ec385c | ||
|
|
84f6fbcfc8 | ||
|
|
4a2d234ba3 | ||
|
|
4841b04076 | ||
|
|
993768ae9b | ||
|
|
624b9d154c | ||
|
|
53a097784e | ||
|
|
511110f466 | ||
|
|
d5170b6874 | ||
|
|
925c99bb9e | ||
|
|
d65af508a3 | ||
|
|
eae70bb20f | ||
|
|
c96cab58ff | ||
|
|
a6d57e4048 | ||
|
|
cb52dd909d | ||
|
|
acca6adacc | ||
|
|
dc4aeb1e51 | ||
|
|
ea1b333da3 | ||
|
|
eb8bd80d48 | ||
|
|
cddcf99873 | ||
|
|
bef39120d3 | ||
|
|
ad3d657db9 | ||
|
|
27a058a3ce | ||
|
|
0d4310184e | ||
|
|
0fbd7641c0 | ||
|
|
60a0e82587 | ||
|
|
1a67d8b0e1 | ||
|
|
1a78209408 | ||
|
|
c05a1c48cb | ||
|
|
32327c6d72 |
@@ -28,38 +28,116 @@ jobs:
|
|||||||
run:
|
run:
|
||||||
shell: bash
|
shell: bash
|
||||||
env:
|
env:
|
||||||
RELEASE_TOKEN: ${{ secrets.GITHUB_TOKEN || secrets.GITEA_TOKEN }}
|
RELEASE_TOKEN: ${{ secrets.RELEASE_PAT }}
|
||||||
SUMMARY_FILE: ${{ runner.temp }}/do-release-summary.md
|
SUMMARY_FILE: ${{ runner.temp }}/do-release-summary.md
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout tagged revision
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
ref: ${{ github.ref }}
|
|
||||||
|
|
||||||
- name: Checkout requested tag
|
- name: Fetch and detect release tag
|
||||||
if: ${{ inputs.tag != '' }}
|
id: detect-tag
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# Fetch all tags from origin first
|
||||||
|
git fetch origin --tags --force --quiet 2>/dev/null || true
|
||||||
|
|
||||||
|
# Check if HEAD is at a tag (prepare-release may have just tagged it)
|
||||||
|
if head_tag="$(git describe --exact-match --tags HEAD 2>/dev/null)" && [[ -n "$head_tag" ]]; then
|
||||||
|
echo "detected_tag=$head_tag" >> "$GITHUB_OUTPUT"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Fall back to finding the most recent tag
|
||||||
|
if latest_tag="$(git describe --tags --abbrev=0 2>/dev/null)" && [[ -n "$latest_tag" ]]; then
|
||||||
|
echo "detected_tag=$latest_tag" >> "$GITHUB_OUTPUT"
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Resolve release version
|
||||||
|
id: resolve-version
|
||||||
|
env:
|
||||||
|
INPUT_TAG: ${{ inputs.tag }}
|
||||||
|
CALLER_TAG: ${{ needs.prepare.outputs.tag }}
|
||||||
|
DETECTED_TAG: ${{ steps.detect-tag.outputs.detected_tag }}
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
normalize_candidate() {
|
||||||
|
local raw="$1"
|
||||||
|
|
||||||
|
raw="$(printf '%s' "$raw" | sed 's/^[[:space:]]\+//; s/[[:space:]]\+$//')"
|
||||||
|
|
||||||
|
# Teacup can surface expression strings as %!t(string=value); unwrap it.
|
||||||
|
if [[ "$raw" =~ ^%\!t\(string=(.*)\)$ ]]; then
|
||||||
|
raw="${BASH_REMATCH[1]}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
raw="$(printf '%s' "$raw" | sed 's/^[[:space:]]\+//; s/[[:space:]]\+$//')"
|
||||||
|
printf '%s' "$raw"
|
||||||
|
}
|
||||||
|
|
||||||
|
input_tag="$(normalize_candidate "${INPUT_TAG}")"
|
||||||
|
caller_tag="$(normalize_candidate "${CALLER_TAG}")"
|
||||||
|
detected_tag="$(normalize_candidate "${DETECTED_TAG}")"
|
||||||
|
|
||||||
|
# Try explicit input first.
|
||||||
|
requested_tag="$input_tag"
|
||||||
|
|
||||||
|
# Fall back to caller workflow output when workflow_call input forwarding is unreliable.
|
||||||
|
if [[ -z "$requested_tag" && -n "$caller_tag" ]]; then
|
||||||
|
requested_tag="$caller_tag"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Fall back to detected tag if neither input nor caller tag is available.
|
||||||
|
if [[ -z "$requested_tag" && -n "$detected_tag" ]]; then
|
||||||
|
requested_tag="$detected_tag"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Try GITHUB_REF if still empty
|
||||||
|
if [[ -z "$requested_tag" && "$GITHUB_REF" == refs/tags/* ]]; then
|
||||||
|
requested_tag="${GITHUB_REF#refs/tags/}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -n "$requested_tag" ]]; then
|
||||||
|
# Normalize to v-prefixed format
|
||||||
|
normalized="${requested_tag#v}"
|
||||||
|
tag="v${normalized}"
|
||||||
|
else
|
||||||
|
echo "Error: Could not resolve release version" >&2
|
||||||
|
echo " - inputs.tag(raw): '$INPUT_TAG'" >&2
|
||||||
|
echo " - needs.prepare.outputs.tag(raw): '$CALLER_TAG'" >&2
|
||||||
|
echo " - detected_tag(raw): '${DETECTED_TAG}'" >&2
|
||||||
|
echo " - GITHUB_REF: '$GITHUB_REF'" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "tag=${tag}" >> "$GITHUB_OUTPUT"
|
||||||
|
echo "version=${normalized}" >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
|
- name: Checkout release tag
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
ref: ${{ startsWith(inputs.tag, 'v') && format('refs/tags/{0}', inputs.tag) || format('refs/tags/v{0}', inputs.tag) }}
|
ref: refs/tags/${{ steps.resolve-version.outputs.tag }}
|
||||||
|
|
||||||
- name: Setup Go
|
- name: Setup Go
|
||||||
uses: actions/setup-go@v5
|
uses: actions/setup-go@v5
|
||||||
with:
|
with:
|
||||||
go-version: '1.26.1'
|
go-version-file: go.mod
|
||||||
check-latest: true
|
check-latest: false
|
||||||
cache: true
|
cache: true
|
||||||
cache-dependency-path: go.sum
|
cache-dependency-path: go.sum
|
||||||
|
|
||||||
- name: Preflight release API access
|
- name: Preflight release API access
|
||||||
env:
|
env:
|
||||||
REQUESTED_TAG: ${{ inputs.tag }}
|
TAG_NAME: ${{ steps.resolve-version.outputs.tag }}
|
||||||
run: |
|
run: |
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
if [[ -z "${RELEASE_TOKEN:-}" ]]; then
|
if [[ -z "${RELEASE_TOKEN:-}" ]]; then
|
||||||
echo "No release token available. Set GITEA_TOKEN (or GITHUB_TOKEN on GitHub)." >&2
|
echo "No release token available. Set secrets.RELEASE_PAT." >&2
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -76,22 +154,17 @@ jobs:
|
|||||||
-H "Content-Type: application/json" \
|
-H "Content-Type: application/json" \
|
||||||
"${repo_api}/releases?limit=1" >/dev/null
|
"${repo_api}/releases?limit=1" >/dev/null
|
||||||
|
|
||||||
requested_tag="$(printf '%s' "${REQUESTED_TAG:-}" | sed 's/^[[:space:]]\+//; s/[[:space:]]\+$//')"
|
if ! git rev-parse --verify --quiet "refs/tags/${TAG_NAME}" >/dev/null; then
|
||||||
if [[ -n "$requested_tag" ]]; then
|
echo "Tag ${TAG_NAME} was not found in the checked out repository." >&2
|
||||||
normalized_tag="${requested_tag#v}"
|
exit 1
|
||||||
tag_ref="refs/tags/v${normalized_tag}"
|
|
||||||
if ! git rev-parse --verify --quiet "$tag_ref" >/dev/null; then
|
|
||||||
echo "Requested tag ${tag_ref#refs/tags/} was not found in the checked out repository." >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
- name: Create or update release
|
- name: Create or update release
|
||||||
id: publish
|
id: publish
|
||||||
uses: ./publish
|
uses: ./publish
|
||||||
with:
|
with:
|
||||||
token: ${{ secrets.GITHUB_TOKEN || secrets.GITEA_TOKEN }}
|
token: ${{ secrets.RELEASE_PAT }}
|
||||||
version: ${{ inputs.tag }}
|
version: ${{ steps.resolve-version.outputs.version }}
|
||||||
|
|
||||||
- name: Build release binaries
|
- name: Build release binaries
|
||||||
env:
|
env:
|
||||||
@@ -211,7 +284,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Download released binary
|
- name: Download released binary
|
||||||
env:
|
env:
|
||||||
TOKEN: ${{ secrets.GITHUB_TOKEN || secrets.GITEA_TOKEN }}
|
TOKEN: ${{ secrets.RELEASE_PAT }}
|
||||||
TAG_NAME: ${{ needs.release.outputs.tag }}
|
TAG_NAME: ${{ needs.release.outputs.tag }}
|
||||||
RELEASE_VERSION: ${{ needs.release.outputs.version }}
|
RELEASE_VERSION: ${{ needs.release.outputs.version }}
|
||||||
ASSET_ARCH: ${{ matrix.asset_arch }}
|
ASSET_ARCH: ${{ matrix.asset_arch }}
|
||||||
|
|||||||
@@ -34,8 +34,8 @@ jobs:
|
|||||||
- name: Setup Go
|
- name: Setup Go
|
||||||
uses: actions/setup-go@v5
|
uses: actions/setup-go@v5
|
||||||
with:
|
with:
|
||||||
go-version: '1.26.1'
|
go-version-file: go.mod
|
||||||
check-latest: true
|
check-latest: false
|
||||||
cache: true
|
cache: true
|
||||||
cache-dependency-path: go.sum
|
cache-dependency-path: go.sum
|
||||||
|
|
||||||
@@ -45,8 +45,15 @@ jobs:
|
|||||||
- name: Module hygiene
|
- name: Module hygiene
|
||||||
run: |
|
run: |
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
go mod tidy
|
go mod tidy
|
||||||
go mod verify
|
|
||||||
|
if ! go mod verify; then
|
||||||
|
echo "go mod verify failed; refreshing module cache and retrying" >&2
|
||||||
|
go clean -modcache
|
||||||
|
go mod download
|
||||||
|
go mod verify
|
||||||
|
fi
|
||||||
|
|
||||||
- name: Restore cached gosec binary
|
- name: Restore cached gosec binary
|
||||||
id: cache-gosec
|
id: cache-gosec
|
||||||
@@ -70,6 +77,8 @@ jobs:
|
|||||||
- name: Run govulncheck
|
- name: Run govulncheck
|
||||||
uses: golang/govulncheck-action@v1.0.4
|
uses: golang/govulncheck-action@v1.0.4
|
||||||
with:
|
with:
|
||||||
|
go-version-file: go.mod
|
||||||
|
check-latest: false
|
||||||
go-package: ./...
|
go-package: ./...
|
||||||
cache: true
|
cache: true
|
||||||
cache-dependency-path: go.sum
|
cache-dependency-path: go.sum
|
||||||
@@ -115,17 +124,313 @@ jobs:
|
|||||||
VOCIFERATE_CACHE_TOKEN: ${{ steps.cache-token.outputs.value }}
|
VOCIFERATE_CACHE_TOKEN: ${{ steps.cache-token.outputs.value }}
|
||||||
with:
|
with:
|
||||||
version: ${{ steps.resolve-version.outputs.tag }}
|
version: ${{ steps.resolve-version.outputs.tag }}
|
||||||
|
token: ${{ secrets.RELEASE_PAT }}
|
||||||
git-add-files: CHANGELOG.md release-version README.md AGENTS.md
|
git-add-files: CHANGELOG.md release-version README.md AGENTS.md
|
||||||
|
|
||||||
- name: Summarize prepared release
|
- name: Summary
|
||||||
|
if: ${{ always() }}
|
||||||
run: |
|
run: |
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
tag="${{ steps.prepare.outputs.version }}"
|
tag="${{ steps.prepare.outputs.version }}"
|
||||||
{
|
{
|
||||||
echo "## Release Prepared"
|
echo "## Release Prepared"
|
||||||
echo
|
echo
|
||||||
echo "- Tag pushed: ${tag}"
|
echo "- Tag pushed: ${tag}"
|
||||||
echo "- Calling Do Release workflow for ${tag}."
|
} >> "$SUMMARY_FILE"
|
||||||
|
|
||||||
|
echo 'Summary'
|
||||||
|
echo
|
||||||
|
|
||||||
|
if [[ -s "$SUMMARY_FILE" ]]; then
|
||||||
|
cat "$SUMMARY_FILE"
|
||||||
|
else
|
||||||
|
echo 'No summary generated.'
|
||||||
|
fi
|
||||||
|
|
||||||
|
release:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
container: docker.io/catthehacker/ubuntu:act-latest
|
||||||
|
needs: prepare
|
||||||
|
outputs:
|
||||||
|
tag: ${{ steps.publish.outputs.tag }}
|
||||||
|
version: ${{ steps.publish.outputs.version }}
|
||||||
|
defaults:
|
||||||
|
run:
|
||||||
|
shell: bash
|
||||||
|
env:
|
||||||
|
RELEASE_TOKEN: ${{ secrets.RELEASE_PAT }}
|
||||||
|
SUMMARY_FILE: ${{ runner.temp }}/release-summary.md
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- name: Resolve release version
|
||||||
|
id: resolve-version
|
||||||
|
env:
|
||||||
|
PREPARE_TAG: ${{ needs.prepare.outputs.tag }}
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
tag="$(printf '%s' "${PREPARE_TAG}" | sed 's/^[[:space:]]\+//; s/[[:space:]]\+$//')"
|
||||||
|
|
||||||
|
# Unwrap Teacup expression strings if present.
|
||||||
|
if [[ "${tag}" =~ ^%\!t\(string=(.*)\)$ ]]; then
|
||||||
|
tag="${BASH_REMATCH[1]}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
normalized="${tag#v}"
|
||||||
|
tag="v${normalized}"
|
||||||
|
echo "tag=${tag}" >> "$GITHUB_OUTPUT"
|
||||||
|
echo "version=${normalized}" >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
|
- name: Checkout release tag
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
ref: refs/tags/${{ steps.resolve-version.outputs.tag }}
|
||||||
|
|
||||||
|
- name: Setup Go
|
||||||
|
uses: actions/setup-go@v5
|
||||||
|
with:
|
||||||
|
go-version-file: go.mod
|
||||||
|
check-latest: false
|
||||||
|
cache: true
|
||||||
|
cache-dependency-path: go.sum
|
||||||
|
|
||||||
|
- name: Preflight release API access
|
||||||
|
env:
|
||||||
|
TAG_NAME: ${{ steps.resolve-version.outputs.tag }}
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
if [[ -z "${RELEASE_TOKEN:-}" ]]; then
|
||||||
|
echo "No release token available. Set secrets.RELEASE_PAT." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
api_base="${GITHUB_API_URL:-${GITHUB_SERVER_URL%/}/api/v1}"
|
||||||
|
repo_api="${api_base}/repos/${GITHUB_REPOSITORY}"
|
||||||
|
|
||||||
|
curl --fail-with-body -sS \
|
||||||
|
-H "Authorization: token ${RELEASE_TOKEN}" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
"${repo_api}" >/dev/null
|
||||||
|
|
||||||
|
curl --fail-with-body -sS \
|
||||||
|
-H "Authorization: token ${RELEASE_TOKEN}" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
"${repo_api}/releases?limit=1" >/dev/null
|
||||||
|
|
||||||
|
if ! git rev-parse --verify --quiet "refs/tags/${TAG_NAME}" >/dev/null; then
|
||||||
|
echo "Tag ${TAG_NAME} was not found in the checked out repository." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Create or update release
|
||||||
|
id: publish
|
||||||
|
uses: ./publish
|
||||||
|
with:
|
||||||
|
token: ${{ secrets.RELEASE_PAT }}
|
||||||
|
version: ${{ steps.resolve-version.outputs.version }}
|
||||||
|
|
||||||
|
- name: Build release binaries
|
||||||
|
env:
|
||||||
|
RELEASE_VERSION: ${{ steps.publish.outputs.version }}
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
mkdir -p dist
|
||||||
|
|
||||||
|
for target in linux/amd64 linux/arm64; do
|
||||||
|
os="${target%/*}"
|
||||||
|
arch="${target#*/}"
|
||||||
|
|
||||||
|
bin="vociferate_${RELEASE_VERSION}_${os}_${arch}"
|
||||||
|
GOOS="$os" GOARCH="$arch" go build -trimpath -ldflags="-s -w" -o "dist/${bin}" ./cmd/vociferate
|
||||||
|
done
|
||||||
|
|
||||||
|
(
|
||||||
|
cd dist
|
||||||
|
shasum -a 256 * > checksums.txt
|
||||||
|
)
|
||||||
|
|
||||||
|
- name: Upload release binaries
|
||||||
|
env:
|
||||||
|
RELEASE_ID: ${{ steps.publish.outputs.release-id }}
|
||||||
|
RELEASE_VERSION: ${{ steps.publish.outputs.version }}
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
raw_release_id="$(printf '%s' "${RELEASE_ID:-}" | sed 's/^[[:space:]]\+//; s/[[:space:]]\+$//')"
|
||||||
|
if [[ "$raw_release_id" =~ ^%\!t\(string=(.*)\)$ ]]; then
|
||||||
|
raw_release_id="${BASH_REMATCH[1]}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
release_id="$(printf '%s' "$raw_release_id" | sed 's/^[[:space:]]\+//; s/[[:space:]]\+$//')"
|
||||||
|
if ! [[ "$release_id" =~ ^[0-9]+$ ]]; then
|
||||||
|
echo "Invalid release id from publish step: '${RELEASE_ID}'" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
release_detail_api="${GITHUB_API_URL:-${GITHUB_SERVER_URL%/}/api/v1}/repos/${GITHUB_REPOSITORY}/releases/${release_id}"
|
||||||
|
if ! curl --fail-with-body -sS \
|
||||||
|
-H "Authorization: token ${RELEASE_TOKEN}" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
"$release_detail_api" >/dev/null; then
|
||||||
|
echo "Resolved release endpoint is not accessible: ${release_detail_api}" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
release_api="${GITHUB_API_URL:-${GITHUB_SERVER_URL%/}/api/v1}/repos/${GITHUB_REPOSITORY}/releases/${release_id}/assets"
|
||||||
|
|
||||||
|
for asset in dist/*; do
|
||||||
|
name="$(basename "$asset")"
|
||||||
|
|
||||||
|
assets_json="$(curl -sS --fail-with-body \
|
||||||
|
-H "Authorization: token ${RELEASE_TOKEN}" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
"${release_api}")"
|
||||||
|
|
||||||
|
escaped_name="$(printf '%s' "$name" | sed 's/[][(){}.^$*+?|\\/]/\\&/g')"
|
||||||
|
existing_asset_id="$(printf '%s' "$assets_json" | tr -d '\n' | sed -n "s/.*{\"id\":\([0-9][0-9]*\)[^}]*\"name\":\"${escaped_name}\".*/\1/p")"
|
||||||
|
|
||||||
|
if [[ -n "$existing_asset_id" ]]; then
|
||||||
|
curl --fail-with-body \
|
||||||
|
-X DELETE \
|
||||||
|
-H "Authorization: token ${RELEASE_TOKEN}" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
"${release_api}/${existing_asset_id}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
curl --fail-with-body \
|
||||||
|
-X POST \
|
||||||
|
-H "Authorization: token ${RELEASE_TOKEN}" \
|
||||||
|
-H "Content-Type: application/octet-stream" \
|
||||||
|
"${release_api}?name=${name}" \
|
||||||
|
--data-binary "@${asset}"
|
||||||
|
done
|
||||||
|
|
||||||
|
- name: Summary
|
||||||
|
if: ${{ always() }}
|
||||||
|
env:
|
||||||
|
TAG_NAME: ${{ steps.publish.outputs.tag }}
|
||||||
|
RELEASE_VERSION: ${{ steps.publish.outputs.version }}
|
||||||
|
PUBLISH_OUTCOME: ${{ steps.publish.outcome }}
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
if [[ "${PUBLISH_OUTCOME}" == "success" ]]; then
|
||||||
|
{
|
||||||
|
echo "## Release Published"
|
||||||
|
echo
|
||||||
|
echo "- Tag: ${TAG_NAME}"
|
||||||
|
echo "- Release notes sourced from changelog entry ${RELEASE_VERSION}."
|
||||||
|
echo "- Published assets: vociferate_${RELEASE_VERSION}_linux_amd64, vociferate_${RELEASE_VERSION}_linux_arm64, checksums.txt"
|
||||||
|
} >> "$SUMMARY_FILE"
|
||||||
|
else
|
||||||
|
{
|
||||||
|
echo "## Release Failed"
|
||||||
|
echo
|
||||||
|
echo "- Tag: ${TAG_NAME:-unknown}"
|
||||||
|
echo "- Create or update release step did not complete successfully."
|
||||||
|
} >> "$SUMMARY_FILE"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo 'Summary'
|
||||||
|
echo
|
||||||
|
|
||||||
|
if [[ -s "$SUMMARY_FILE" ]]; then
|
||||||
|
cat "$SUMMARY_FILE"
|
||||||
|
else
|
||||||
|
echo 'No summary generated.'
|
||||||
|
fi
|
||||||
|
|
||||||
|
validate:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
container: docker.io/catthehacker/ubuntu:act-latest
|
||||||
|
needs: release
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
- asset_arch: amd64
|
||||||
|
run_command: ./vociferate
|
||||||
|
- asset_arch: arm64
|
||||||
|
run_command: qemu-aarch64-static ./vociferate
|
||||||
|
defaults:
|
||||||
|
run:
|
||||||
|
shell: bash
|
||||||
|
env:
|
||||||
|
SUMMARY_FILE: ${{ runner.temp }}/validate-summary.md
|
||||||
|
steps:
|
||||||
|
- name: Checkout tagged revision
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
ref: refs/tags/${{ needs.release.outputs.tag }}
|
||||||
|
|
||||||
|
- name: Install arm64 emulator
|
||||||
|
if: ${{ matrix.asset_arch == 'arm64' }}
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
apt-get update
|
||||||
|
apt-get install -y qemu-user-static
|
||||||
|
|
||||||
|
- name: Download released binary
|
||||||
|
env:
|
||||||
|
TOKEN: ${{ secrets.RELEASE_PAT }}
|
||||||
|
TAG_NAME: ${{ needs.release.outputs.tag }}
|
||||||
|
RELEASE_VERSION: ${{ needs.release.outputs.version }}
|
||||||
|
ASSET_ARCH: ${{ matrix.asset_arch }}
|
||||||
|
SERVER_URL: ${{ github.server_url }}
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
asset_name="vociferate_${RELEASE_VERSION}_linux_${ASSET_ARCH}"
|
||||||
|
asset_url="${SERVER_URL}/aether/vociferate/releases/download/${TAG_NAME}/${asset_name}"
|
||||||
|
|
||||||
|
curl --fail --location \
|
||||||
|
-H "Authorization: token ${TOKEN}" \
|
||||||
|
-o vociferate \
|
||||||
|
"$asset_url"
|
||||||
|
chmod +x vociferate
|
||||||
|
|
||||||
|
echo "asset_name=${asset_name}" >> "$GITHUB_ENV"
|
||||||
|
|
||||||
|
- name: Smoke test released binary
|
||||||
|
env:
|
||||||
|
RUN_COMMAND: ${{ matrix.run_command }}
|
||||||
|
TAG_NAME: ${{ needs.release.outputs.tag }}
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
${RUN_COMMAND} --help >/dev/null
|
||||||
|
|
||||||
|
recommend_stderr="$(mktemp)"
|
||||||
|
if ${RUN_COMMAND} --recommend --root . >/dev/null 2>"${recommend_stderr}"; then
|
||||||
|
echo "Expected --recommend to fail on the tagged release checkout" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
recommend_error="$(cat "${recommend_stderr}")"
|
||||||
|
case "${recommend_error}" in
|
||||||
|
*"unreleased section is empty"*)
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Unexpected recommend failure output: ${recommend_error}" >&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
{
|
||||||
|
echo "## Released Binary Validation (${{ matrix.asset_arch }})"
|
||||||
|
echo
|
||||||
|
echo "- Release tag: ${TAG_NAME}"
|
||||||
|
echo "- Asset: ${asset_name}"
|
||||||
|
echo "- Binary executed successfully via --help."
|
||||||
|
echo "- --recommend failed as expected on the tagged checkout because Unreleased is empty."
|
||||||
} >> "$SUMMARY_FILE"
|
} >> "$SUMMARY_FILE"
|
||||||
|
|
||||||
- name: Summary
|
- name: Summary
|
||||||
@@ -141,10 +446,3 @@ jobs:
|
|||||||
else
|
else
|
||||||
echo 'No summary generated.'
|
echo 'No summary generated.'
|
||||||
fi
|
fi
|
||||||
|
|
||||||
publish:
|
|
||||||
needs: prepare
|
|
||||||
uses: ./.gitea/workflows/do-release.yml
|
|
||||||
with:
|
|
||||||
tag: ${{ needs.prepare.outputs.tag }}
|
|
||||||
secrets: inherit
|
|
||||||
|
|||||||
@@ -30,8 +30,8 @@ jobs:
|
|||||||
- name: Setup Go
|
- name: Setup Go
|
||||||
uses: actions/setup-go@v5
|
uses: actions/setup-go@v5
|
||||||
with:
|
with:
|
||||||
go-version: '1.26.1'
|
go-version-file: go.mod
|
||||||
check-latest: true
|
check-latest: false
|
||||||
cache: true
|
cache: true
|
||||||
cache-dependency-path: go.sum
|
cache-dependency-path: go.sum
|
||||||
|
|
||||||
@@ -41,8 +41,15 @@ jobs:
|
|||||||
- name: Module hygiene
|
- name: Module hygiene
|
||||||
run: |
|
run: |
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
go mod tidy
|
go mod tidy
|
||||||
go mod verify
|
|
||||||
|
if ! go mod verify; then
|
||||||
|
echo "go mod verify failed; refreshing module cache and retrying" >&2
|
||||||
|
go clean -modcache
|
||||||
|
go mod download
|
||||||
|
go mod verify
|
||||||
|
fi
|
||||||
|
|
||||||
- name: Restore cached gosec binary
|
- name: Restore cached gosec binary
|
||||||
id: cache-gosec
|
id: cache-gosec
|
||||||
@@ -66,6 +73,8 @@ jobs:
|
|||||||
- name: Run govulncheck
|
- name: Run govulncheck
|
||||||
uses: golang/govulncheck-action@v1.0.4
|
uses: golang/govulncheck-action@v1.0.4
|
||||||
with:
|
with:
|
||||||
|
go-version-file: go.mod
|
||||||
|
check-latest: false
|
||||||
go-package: ./...
|
go-package: ./...
|
||||||
cache: true
|
cache: true
|
||||||
cache-dependency-path: go.sum
|
cache-dependency-path: go.sum
|
||||||
@@ -115,8 +124,8 @@ jobs:
|
|||||||
- name: Setup Go
|
- name: Setup Go
|
||||||
uses: actions/setup-go@v5
|
uses: actions/setup-go@v5
|
||||||
with:
|
with:
|
||||||
go-version: '1.26.1'
|
go-version-file: go.mod
|
||||||
check-latest: true
|
check-latest: false
|
||||||
cache: true
|
cache: true
|
||||||
cache-dependency-path: go.sum
|
cache-dependency-path: go.sum
|
||||||
|
|
||||||
|
|||||||
26
AGENTS.md
26
AGENTS.md
@@ -4,15 +4,15 @@ This guide is for agentic coding partners that need to integrate the composite a
|
|||||||
|
|
||||||
## Source Of Truth
|
## Source Of Truth
|
||||||
|
|
||||||
Pin all action references to a released tag (for example `@v1.0.2`) and keep all vociferate references on the same tag in a workflow.
|
Pin all action references to a released tag (for example `@v1.1.0`) and keep all vociferate references on the same tag in a workflow.
|
||||||
|
|
||||||
Published composite actions:
|
Published composite actions:
|
||||||
|
|
||||||
- `https://git.hrafn.xyz/aether/vociferate@v1.0.2` (root action)
|
- `https://git.hrafn.xyz/aether/vociferate@v1.1.0` (root action)
|
||||||
- `https://git.hrafn.xyz/aether/vociferate/prepare@v1.0.2`
|
- `https://git.hrafn.xyz/aether/vociferate/prepare@v1.1.0`
|
||||||
- `https://git.hrafn.xyz/aether/vociferate/publish@v1.0.2`
|
- `https://git.hrafn.xyz/aether/vociferate/publish@v1.1.0`
|
||||||
- `https://git.hrafn.xyz/aether/vociferate/coverage-badge@v1.0.2`
|
- `https://git.hrafn.xyz/aether/vociferate/coverage-badge@v1.1.0`
|
||||||
- `https://git.hrafn.xyz/aether/vociferate/decorate-pr@v1.0.2`
|
- `https://git.hrafn.xyz/aether/vociferate/decorate-pr@v1.1.0`
|
||||||
|
|
||||||
## Action Selection Matrix
|
## Action Selection Matrix
|
||||||
|
|
||||||
@@ -30,7 +30,7 @@ Apply these checks before invoking actions:
|
|||||||
|
|
||||||
- Checkout repository first.
|
- Checkout repository first.
|
||||||
- For prepare/publish flows that depend on tags/history, use full history checkout (`fetch-depth: 0`).
|
- For prepare/publish flows that depend on tags/history, use full history checkout (`fetch-depth: 0`).
|
||||||
- Use valid credentials for release/comment API calls. On GitHub, `secrets.GITHUB_TOKEN` is used; on self-hosted Gitea, set `secrets.GITEA_TOKEN`.
|
- Use `secrets.RELEASE_PAT` for release/tag/update operations (prepare/publish/do-release) so tag pushes trigger downstream workflows reliably.
|
||||||
- `do-release` and `decorate-pr` now run preflight API checks and fail fast when token credentials are missing or insufficient.
|
- `do-release` and `decorate-pr` now run preflight API checks and fail fast when token credentials are missing or insufficient.
|
||||||
- Set required vars/secrets for coverage uploads:
|
- Set required vars/secrets for coverage uploads:
|
||||||
- `vars.ARTEFACT_BUCKET_NAME`
|
- `vars.ARTEFACT_BUCKET_NAME`
|
||||||
@@ -94,11 +94,11 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
- id: prepare
|
- id: prepare
|
||||||
uses: https://git.hrafn.xyz/aether/vociferate/prepare@v1.0.2
|
uses: https://git.hrafn.xyz/aether/vociferate/prepare@v1.1.0
|
||||||
|
|
||||||
publish:
|
publish:
|
||||||
needs: prepare
|
needs: prepare
|
||||||
uses: https://git.hrafn.xyz/aether/vociferate/.gitea/workflows/do-release.yml@v1.0.2
|
uses: https://git.hrafn.xyz/aether/vociferate/.gitea/workflows/do-release.yml@v1.1.0
|
||||||
with:
|
with:
|
||||||
tag: ${{ needs.prepare.outputs.version }}
|
tag: ${{ needs.prepare.outputs.version }}
|
||||||
secrets: inherit
|
secrets: inherit
|
||||||
@@ -115,7 +115,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
- id: publish
|
- id: publish
|
||||||
uses: https://git.hrafn.xyz/aether/vociferate/publish@v1.0.2
|
uses: https://git.hrafn.xyz/aether/vociferate/publish@v1.1.0
|
||||||
with:
|
with:
|
||||||
version: v1.2.3
|
version: v1.2.3
|
||||||
```
|
```
|
||||||
@@ -136,7 +136,7 @@ jobs:
|
|||||||
- name: Run tests with coverage
|
- name: Run tests with coverage
|
||||||
run: go test -covermode=atomic -coverprofile=coverage.out ./...
|
run: go test -covermode=atomic -coverprofile=coverage.out ./...
|
||||||
- id: badge
|
- id: badge
|
||||||
uses: https://git.hrafn.xyz/aether/vociferate/coverage-badge@v1.0.2
|
uses: https://git.hrafn.xyz/aether/vociferate/coverage-badge@v1.1.0
|
||||||
with:
|
with:
|
||||||
artefact-bucket-name: ${{ vars.ARTEFACT_BUCKET_NAME }}
|
artefact-bucket-name: ${{ vars.ARTEFACT_BUCKET_NAME }}
|
||||||
artefact-bucket-endpoint: ${{ vars.ARTEFACT_BUCKET_ENDPONT }}
|
artefact-bucket-endpoint: ${{ vars.ARTEFACT_BUCKET_ENDPONT }}
|
||||||
@@ -159,12 +159,12 @@ jobs:
|
|||||||
- name: Run tests with coverage
|
- name: Run tests with coverage
|
||||||
run: go test -covermode=atomic -coverprofile=coverage.out ./...
|
run: go test -covermode=atomic -coverprofile=coverage.out ./...
|
||||||
- id: badge
|
- id: badge
|
||||||
uses: https://git.hrafn.xyz/aether/vociferate/coverage-badge@v1.0.2
|
uses: https://git.hrafn.xyz/aether/vociferate/coverage-badge@v1.1.0
|
||||||
with:
|
with:
|
||||||
artefact-bucket-name: ${{ vars.ARTEFACT_BUCKET_NAME }}
|
artefact-bucket-name: ${{ vars.ARTEFACT_BUCKET_NAME }}
|
||||||
artefact-bucket-endpoint: ${{ vars.ARTEFACT_BUCKET_ENDPONT }}
|
artefact-bucket-endpoint: ${{ vars.ARTEFACT_BUCKET_ENDPONT }}
|
||||||
- name: Decorate PR
|
- name: Decorate PR
|
||||||
uses: https://git.hrafn.xyz/aether/vociferate/decorate-pr@v1.0.2
|
uses: https://git.hrafn.xyz/aether/vociferate/decorate-pr@v1.1.0
|
||||||
with:
|
with:
|
||||||
coverage-percentage: ${{ steps.badge.outputs.total }}
|
coverage-percentage: ${{ steps.badge.outputs.total }}
|
||||||
badge-url: ${{ steps.badge.outputs.badge-url }}
|
badge-url: ${{ steps.badge.outputs.badge-url }}
|
||||||
|
|||||||
33
CHANGELOG.md
33
CHANGELOG.md
@@ -13,6 +13,18 @@ A `### Breaking` section is used in addition to Keep a Changelog's standard sect
|
|||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
### Removed
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
## [1.1.0] - 2026-03-21
|
||||||
|
|
||||||
|
### Breaking
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
- Added changelog gate validation to `decorate-pr` action for enforcing changelog updates on qualifying code changes.
|
- Added changelog gate validation to `decorate-pr` action for enforcing changelog updates on qualifying code changes.
|
||||||
- Changelog gate modes: `strict` (fails job on violation) and `soft` (warns via PR comment).
|
- Changelog gate modes: `strict` (fails job on violation) and `soft` (warns via PR comment).
|
||||||
- Docs-only PR exemption with customizable glob patterns for documentation files.
|
- Docs-only PR exemption with customizable glob patterns for documentation files.
|
||||||
@@ -29,17 +41,27 @@ A `### Breaking` section is used in addition to Keep a Changelog's standard sect
|
|||||||
- `decorate-pr` now reads Unreleased changelog content through the `vociferate` Go CLI instead of maintaining separate shell parsing logic in the composite action.
|
- `decorate-pr` now reads Unreleased changelog content through the `vociferate` Go CLI instead of maintaining separate shell parsing logic in the composite action.
|
||||||
- `publish` now extracts tagged release notes through the `vociferate` Go CLI instead of duplicating changelog section parsing in shell.
|
- `publish` now extracts tagged release notes through the `vociferate` Go CLI instead of duplicating changelog section parsing in shell.
|
||||||
- Composite actions now share a centralized `run-vociferate` orchestration flow, with binary-versus-source execution delegated through shared composite actions and single-use runtime/download logic folded back into `run-vociferate.binary`.
|
- Composite actions now share a centralized `run-vociferate` orchestration flow, with binary-versus-source execution delegated through shared composite actions and single-use runtime/download logic folded back into `run-vociferate.binary`.
|
||||||
- `run-vociferate/binary` and `run-vociferate/code` are now nested under `run-vociferate/` so callers reference them as `./run-vociferate/binary` and `./run-vociferate/code`.
|
- `run-vociferate` now contains both binary and source execution flows directly in a single action implementation, removing nested local action wrappers for better runner compatibility.
|
||||||
|
- Release automation now requires `secrets.RELEASE_PAT` for prepare/publish/do-release operations instead of defaulting to `GITHUB_TOKEN`/`GITEA_TOKEN`.
|
||||||
|
|
||||||
### Removed
|
### Removed
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Fixed `decorate-pr/action.yml` YAML validation by extracting PR comment rendering into `decorate-pr/build-comment.sh`, removing the duplicated changelog extraction step, and correcting the gate failure output reference.
|
- Prevented `govulncheck-action` from defaulting to `setup-go` version `stable` by explicitly setting `go-version-file` and disabling `check-latest`, avoiding unauthenticated GitHub API rate-limit failures on self-hosted/act-style runners.
|
||||||
- Fixed docs-only detection in `decorate-pr` changelog gate: file list was iterated in a piped subshell so `docs_only` never propagated to the parent scope; replaced pipe with process substitution.
|
- Made `do-release` version resolution resilient to `workflow_call` input passing issues by adding a separate tag detection step that fetches and discovers the latest tag from origin as a fallback when `inputs.tag` is empty, enabling proper operation even when Gitea's workflow_call doesn't pass inputs through correctly.
|
||||||
|
- Fixed version resolution in `do-release` workflow by moving version calculation before checkout, resolving from inputs/git tags, and always passing explicit version to `publish` action.
|
||||||
|
- Fixed tag detection in `do-release` to prioritize the tag at current HEAD (created by `prepare-release`) over the globally latest tag, ensuring correct version is detected when called from `prepare-release` workflow.
|
||||||
|
- Fixed `do-release` workflow_call resolution on Teacup runners by explicitly falling back to `needs.prepare.outputs.tag` and normalizing `%!t(string=...)` wrapped values before choosing a release tag.
|
||||||
|
- Fixed release-chain triggering by using a PAT for release commit/tag pushes so downstream release workflows are triggered reliably.
|
||||||
|
- Made `publish` action version resolution more robust with clearer error messages when version input is missing and workflow is not running from a tag push.
|
||||||
|
- Fixed `do-release` workflow to always checkout the resolved release tag, eliminating conditional checkout logic that could skip the checkout when called from `prepare-release` workflow.
|
||||||
- Pinned `securego/gosec` and `golang/govulncheck-action` to concrete version tags (`v2.22.4` and `v1.0.4`) so self-hosted Gitea runners can resolve them via direct git clone without relying on the GitHub Actions floating-tag API.
|
- Pinned `securego/gosec` and `golang/govulncheck-action` to concrete version tags (`v2.22.4` and `v1.0.4`) so self-hosted Gitea runners can resolve them via direct git clone without relying on the GitHub Actions floating-tag API.
|
||||||
- Restored explicit gosec caching by storing a pinned `v2.22.4` binary under `${{ runner.temp }}/gosec-bin` with `actions/cache@v4`, so CI keeps fast security scans while still using the Go 1.26 toolchain from `setup-go`.
|
- Restored explicit gosec caching by storing a pinned `v2.22.4` binary under `${{ runner.temp }}/gosec-bin` with `actions/cache@v4`, so CI keeps fast security scans while still using the Go 1.26 toolchain from `setup-go`.
|
||||||
- Replaced `securego/gosec` composite action with a direct `go install github.com/securego/gosec/v2/cmd/gosec@v2.22.4 && gosec ./...` run step so gosec uses the Go 1.26 toolchain installed by `setup-go` rather than the action's bundled Go 1.24 binary which ignores `GOTOOLCHAIN=auto`.
|
- Replaced `securego/gosec` composite action with a direct `go install github.com/securego/gosec/v2/cmd/gosec@v2.22.4 && gosec ./...` run step so gosec uses the Go 1.26 toolchain installed by `setup-go` rather than the action's bundled Go 1.24 binary which ignores `GOTOOLCHAIN=auto`.
|
||||||
|
- Fixed nested local composite-action references to use repository-local `./run-vociferate` paths so strict runners do not misparse parent-directory (`../`) action references as malformed remote coordinates.
|
||||||
|
- Consolidated `run-vociferate` binary and source execution flows directly into the main `run-vociferate` action to avoid nested local-action path resolution issues on strict runners.
|
||||||
|
- Hardened workflow module hygiene by retrying `go mod verify` after a module-cache refresh (`go clean -modcache` + `go mod download`) when runners report modified cached dependency directories.
|
||||||
|
|
||||||
## [1.0.2] - 2026-03-21
|
## [1.0.2] - 2026-03-21
|
||||||
|
|
||||||
@@ -146,9 +168,10 @@ A `### Breaking` section is used in addition to Keep a Changelog's standard sect
|
|||||||
- Project/automation rename from `releaseprep` to `vociferate` (entrypoint, package paths, outputs).
|
- Project/automation rename from `releaseprep` to `vociferate` (entrypoint, package paths, outputs).
|
||||||
- README guidance focused on primary cross-repository reuse workflows.
|
- README guidance focused on primary cross-repository reuse workflows.
|
||||||
|
|
||||||
[Unreleased]: https://git.hrafn.xyz/aether/vociferate/compare/v1.0.2...main
|
[Unreleased]: https://git.hrafn.xyz/aether/vociferate/compare/v1.1.0...main
|
||||||
|
[1.1.0]: https://git.hrafn.xyz/aether/vociferate/compare/v1.0.2...v1.1.0
|
||||||
[1.0.2]: https://git.hrafn.xyz/aether/vociferate/compare/v1.0.1...v1.0.2
|
[1.0.2]: https://git.hrafn.xyz/aether/vociferate/compare/v1.0.1...v1.0.2
|
||||||
[1.0.1]: https://git.hrafn.xyz/aether/vociferate/compare/v1.0.0...v1.0.1
|
[1.0.1]: https://git.hrafn.xyz/aether/vociferate/compare/v1.0.0...v1.0.1
|
||||||
[1.0.0]: https://git.hrafn.xyz/aether/vociferate/compare/v0.2.0...v1.0.0
|
[1.0.0]: https://git.hrafn.xyz/aether/vociferate/compare/v0.2.0...v1.0.0
|
||||||
[0.2.0]: https://git.hrafn.xyz/aether/vociferate/compare/v0.1.0...v0.2.0
|
[0.2.0]: https://git.hrafn.xyz/aether/vociferate/compare/v0.1.0...v0.2.0
|
||||||
[0.1.0]: https://git.hrafn.xyz/aether/vociferate/compare/2060af6...v0.1.0
|
[0.1.0]: https://git.hrafn.xyz/aether/vociferate/compare/81dced6...v0.1.0
|
||||||
|
|||||||
34
README.md
34
README.md
@@ -17,7 +17,7 @@ revision.
|
|||||||
## Use In Other Repositories
|
## Use In Other Repositories
|
||||||
|
|
||||||
Vociferate ships composite actions covering release preparation, release publication, coverage badge publishing, and pull request decoration.
|
Vociferate ships composite actions covering release preparation, release publication, coverage badge publishing, and pull request decoration.
|
||||||
Release tags now exist; pin all action and reusable-workflow references to the same released tag (for example, `@v1.0.2`) instead of `@main`.
|
Release tags now exist; pin all action and reusable-workflow references to the same released tag (for example, `@v1.1.0`) instead of `@main`.
|
||||||
|
|
||||||
For agentic coding partners, see [`AGENTS.md`](AGENTS.md) for a direct integration playbook, selection matrix, and copy-paste workflow patterns.
|
For agentic coding partners, see [`AGENTS.md`](AGENTS.md) for a direct integration playbook, selection matrix, and copy-paste workflow patterns.
|
||||||
|
|
||||||
@@ -41,13 +41,13 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
- uses: https://git.hrafn.xyz/aether/vociferate/prepare@v1.0.2
|
- uses: https://git.hrafn.xyz/aether/vociferate/prepare@v1.1.0
|
||||||
with:
|
with:
|
||||||
version: ${{ inputs.version }}
|
version: ${{ inputs.version }}
|
||||||
|
|
||||||
publish:
|
publish:
|
||||||
needs: prepare
|
needs: prepare
|
||||||
uses: https://git.hrafn.xyz/aether/vociferate/.gitea/workflows/do-release.yml@v1.0.2
|
uses: https://git.hrafn.xyz/aether/vociferate/.gitea/workflows/do-release.yml@v1.1.0
|
||||||
with:
|
with:
|
||||||
tag: ${{ needs.prepare.outputs.version }}
|
tag: ${{ needs.prepare.outputs.version }}
|
||||||
secrets: inherit
|
secrets: inherit
|
||||||
@@ -61,15 +61,16 @@ For repositories that embed the version inside source code, pass `version-file`
|
|||||||
and `version-pattern`:
|
and `version-pattern`:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
- uses: https://git.hrafn.xyz/aether/vociferate/prepare@v1.0.2
|
- uses: https://git.hrafn.xyz/aether/vociferate/prepare@v1.1.0
|
||||||
with:
|
with:
|
||||||
|
token: ${{ secrets.RELEASE_PAT }}
|
||||||
version-file: internal/myapp/version/version.go
|
version-file: internal/myapp/version/version.go
|
||||||
version-pattern: 'const Version = "([^"]+)"'
|
version-pattern: 'const Version = "([^"]+)"'
|
||||||
git-add-files: CHANGELOG.md internal/myapp/version/version.go
|
git-add-files: CHANGELOG.md internal/myapp/version/version.go
|
||||||
```
|
```
|
||||||
|
|
||||||
`prepare` uses `github.token` internally for authenticated fetch/push operations,
|
`prepare` requires a PAT input for authenticated commit/push/tag operations.
|
||||||
so no token input is required.
|
Pass `token: ${{ secrets.RELEASE_PAT }}` when invoking the action.
|
||||||
|
|
||||||
### `publish` — create release with changelog notes
|
### `publish` — create release with changelog notes
|
||||||
|
|
||||||
@@ -85,7 +86,7 @@ on:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
release:
|
release:
|
||||||
uses: https://git.hrafn.xyz/aether/vociferate/.gitea/workflows/do-release.yml@v1.0.2
|
uses: https://git.hrafn.xyz/aether/vociferate/.gitea/workflows/do-release.yml@v1.1.0
|
||||||
with:
|
with:
|
||||||
tag: ${{ inputs.tag }}
|
tag: ${{ inputs.tag }}
|
||||||
secrets: inherit
|
secrets: inherit
|
||||||
@@ -96,21 +97,20 @@ Gitea/GitHub release with those notes. The `version` input is optional — when
|
|||||||
omitted it is derived from the current tag ref automatically.
|
omitted it is derived from the current tag ref automatically.
|
||||||
|
|
||||||
The reusable `Do Release` workflow now runs preflight checks before publish to
|
The reusable `Do Release` workflow now runs preflight checks before publish to
|
||||||
fail fast when the release token is missing or lacks API access. On
|
fail fast when the release token is missing or lacks API access. Set
|
||||||
self-hosted Gitea, set `secrets.GITEA_TOKEN`; on GitHub, `secrets.GITHUB_TOKEN`
|
`secrets.RELEASE_PAT` and use it for prepare/publish release operations.
|
||||||
is used automatically.
|
|
||||||
|
|
||||||
The `publish` action outputs `release-id` so you can upload additional release
|
The `publish` action outputs `release-id` so you can upload additional release
|
||||||
assets after it runs:
|
assets after it runs:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
- id: publish
|
- id: publish
|
||||||
uses: https://git.hrafn.xyz/aether/vociferate/publish@v1.0.2
|
uses: https://git.hrafn.xyz/aether/vociferate/publish@v1.1.0
|
||||||
|
|
||||||
- name: Upload my binary
|
- name: Upload my binary
|
||||||
run: |
|
run: |
|
||||||
curl --fail-with-body -X POST \
|
curl --fail-with-body -X POST \
|
||||||
-H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
|
-H "Authorization: token ${{ secrets.RELEASE_PAT }}" \
|
||||||
-H "Content-Type: application/octet-stream" \
|
-H "Content-Type: application/octet-stream" \
|
||||||
"${{ github.api_url }}/repos/${{ github.repository }}/releases/${{ steps.publish.outputs.release-id }}/assets?name=myapp" \
|
"${{ github.api_url }}/repos/${{ github.repository }}/releases/${{ steps.publish.outputs.release-id }}/assets?name=myapp" \
|
||||||
--data-binary "@dist/myapp"
|
--data-binary "@dist/myapp"
|
||||||
@@ -125,7 +125,7 @@ Run your coverage tests first, then call the action to generate `coverage.html`,
|
|||||||
run: go test -covermode=atomic -coverprofile=coverage.out ./...
|
run: go test -covermode=atomic -coverprofile=coverage.out ./...
|
||||||
|
|
||||||
- id: coverage
|
- id: coverage
|
||||||
uses: https://git.hrafn.xyz/aether/vociferate/coverage-badge@v1.0.2
|
uses: https://git.hrafn.xyz/aether/vociferate/coverage-badge@v1.1.0
|
||||||
with:
|
with:
|
||||||
artefact-bucket-name: ${{ vars.ARTEFACT_BUCKET_NAME }}
|
artefact-bucket-name: ${{ vars.ARTEFACT_BUCKET_NAME }}
|
||||||
artefact-bucket-endpoint: ${{ vars.ARTEFACT_BUCKET_ENDPONT }}
|
artefact-bucket-endpoint: ${{ vars.ARTEFACT_BUCKET_ENDPONT }}
|
||||||
@@ -150,14 +150,14 @@ with a clear message when token permissions are insufficient.
|
|||||||
run: go test -covermode=atomic -coverprofile=coverage.out ./...
|
run: go test -covermode=atomic -coverprofile=coverage.out ./...
|
||||||
|
|
||||||
- id: coverage
|
- id: coverage
|
||||||
uses: https://git.hrafn.xyz/aether/vociferate/coverage-badge@v1.0.2
|
uses: https://git.hrafn.xyz/aether/vociferate/coverage-badge@v1.1.0
|
||||||
with:
|
with:
|
||||||
artefact-bucket-name: ${{ vars.ARTEFACT_BUCKET_NAME }}
|
artefact-bucket-name: ${{ vars.ARTEFACT_BUCKET_NAME }}
|
||||||
artefact-bucket-endpoint: ${{ vars.ARTEFACT_BUCKET_ENDPONT }}
|
artefact-bucket-endpoint: ${{ vars.ARTEFACT_BUCKET_ENDPONT }}
|
||||||
|
|
||||||
- name: Decorate pull request
|
- name: Decorate pull request
|
||||||
if: github.event_name == 'pull_request'
|
if: github.event_name == 'pull_request'
|
||||||
uses: https://git.hrafn.xyz/aether/vociferate/decorate-pr@v1.0.2
|
uses: https://git.hrafn.xyz/aether/vociferate/decorate-pr@v1.1.0
|
||||||
with:
|
with:
|
||||||
coverage-percentage: ${{ steps.coverage.outputs.total }}
|
coverage-percentage: ${{ steps.coverage.outputs.total }}
|
||||||
badge-url: ${{ steps.coverage.outputs.badge-url }}
|
badge-url: ${{ steps.coverage.outputs.badge-url }}
|
||||||
@@ -170,7 +170,7 @@ Enable changelog validation to enforce that code changes include `Unreleased` ch
|
|||||||
```yaml
|
```yaml
|
||||||
- name: Decorate pull request with changelog gate
|
- name: Decorate pull request with changelog gate
|
||||||
if: github.event_name == 'pull_request'
|
if: github.event_name == 'pull_request'
|
||||||
uses: https://git.hrafn.xyz/aether/vociferate/decorate-pr@v1.0.2
|
uses: https://git.hrafn.xyz/aether/vociferate/decorate-pr@v1.1.0
|
||||||
with:
|
with:
|
||||||
coverage-percentage: ${{ steps.coverage.outputs.total }}
|
coverage-percentage: ${{ steps.coverage.outputs.total }}
|
||||||
badge-url: ${{ steps.coverage.outputs.badge-url }}
|
badge-url: ${{ steps.coverage.outputs.badge-url }}
|
||||||
@@ -196,7 +196,7 @@ Decision outputs enable downstream workflow logic:
|
|||||||
- name: Decorate PR and check gate
|
- name: Decorate PR and check gate
|
||||||
id: decorate
|
id: decorate
|
||||||
if: github.event_name == 'pull_request'
|
if: github.event_name == 'pull_request'
|
||||||
uses: https://git.hrafn.xyz/aether/vociferate/decorate-pr@v1.0.2
|
uses: https://git.hrafn.xyz/aether/vociferate/decorate-pr@v1.1.0
|
||||||
with:
|
with:
|
||||||
coverage-percentage: ${{ steps.coverage.outputs.total }}
|
coverage-percentage: ${{ steps.coverage.outputs.total }}
|
||||||
badge-url: ${{ steps.coverage.outputs.badge-url }}
|
badge-url: ${{ steps.coverage.outputs.badge-url }}
|
||||||
|
|||||||
@@ -164,7 +164,7 @@ runs:
|
|||||||
- name: Extract changelog unreleased entries
|
- name: Extract changelog unreleased entries
|
||||||
id: extract-changelog
|
id: extract-changelog
|
||||||
if: steps.changelog-file.outputs.exists == 'true'
|
if: steps.changelog-file.outputs.exists == 'true'
|
||||||
uses: ../run-vociferate
|
uses: ./run-vociferate
|
||||||
with:
|
with:
|
||||||
root: ${{ github.workspace }}
|
root: ${{ github.workspace }}
|
||||||
changelog: ${{ inputs.changelog }}
|
changelog: ${{ inputs.changelog }}
|
||||||
|
|||||||
@@ -42,6 +42,11 @@ inputs:
|
|||||||
custom version-file.
|
custom version-file.
|
||||||
required: false
|
required: false
|
||||||
default: 'CHANGELOG.md release-version'
|
default: 'CHANGELOG.md release-version'
|
||||||
|
token:
|
||||||
|
description: >
|
||||||
|
Personal access token used to authenticate commit, push, and tag
|
||||||
|
operations. Required to ensure downstream workflows trigger on tag push.
|
||||||
|
required: true
|
||||||
|
|
||||||
outputs:
|
outputs:
|
||||||
version:
|
version:
|
||||||
@@ -66,7 +71,7 @@ runs:
|
|||||||
- name: Recommend version
|
- name: Recommend version
|
||||||
id: recommend-version
|
id: recommend-version
|
||||||
if: steps.normalize-version.outputs.value == ''
|
if: steps.normalize-version.outputs.value == ''
|
||||||
uses: ../run-vociferate
|
uses: ./run-vociferate
|
||||||
with:
|
with:
|
||||||
root: ${{ github.workspace }}
|
root: ${{ github.workspace }}
|
||||||
version-file: ${{ inputs.version-file }}
|
version-file: ${{ inputs.version-file }}
|
||||||
@@ -102,7 +107,7 @@ runs:
|
|||||||
printf 'value=%s\n' "$(date -u +%F)" >> "$GITHUB_OUTPUT"
|
printf 'value=%s\n' "$(date -u +%F)" >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
- name: Prepare release files
|
- name: Prepare release files
|
||||||
uses: ../run-vociferate
|
uses: ./run-vociferate
|
||||||
with:
|
with:
|
||||||
root: ${{ github.workspace }}
|
root: ${{ github.workspace }}
|
||||||
version-file: ${{ inputs.version-file }}
|
version-file: ${{ inputs.version-file }}
|
||||||
@@ -114,7 +119,7 @@ runs:
|
|||||||
- name: Commit and push release
|
- name: Commit and push release
|
||||||
shell: bash
|
shell: bash
|
||||||
env:
|
env:
|
||||||
TOKEN: ${{ github.token }}
|
TOKEN: ${{ inputs.token }}
|
||||||
GIT_USER_NAME: ${{ inputs.git-user-name }}
|
GIT_USER_NAME: ${{ inputs.git-user-name }}
|
||||||
GIT_USER_EMAIL: ${{ inputs.git-user-email }}
|
GIT_USER_EMAIL: ${{ inputs.git-user-email }}
|
||||||
GIT_ADD_FILES: ${{ inputs.git-add-files }}
|
GIT_ADD_FILES: ${{ inputs.git-add-files }}
|
||||||
@@ -124,6 +129,11 @@ runs:
|
|||||||
run: |
|
run: |
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
|
if [[ -z "${TOKEN:-}" ]]; then
|
||||||
|
echo "A release PAT is required. Provide inputs.token (for example secrets.RELEASE_PAT)." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
case "$GITHUB_SERVER_URL" in
|
case "$GITHUB_SERVER_URL" in
|
||||||
https://*)
|
https://*)
|
||||||
authed_remote="https://oauth2:${TOKEN}@${GITHUB_SERVER_URL#https://}/${GITHUB_REPOSITORY}.git"
|
authed_remote="https://oauth2:${TOKEN}@${GITHUB_SERVER_URL#https://}/${GITHUB_REPOSITORY}.git"
|
||||||
|
|||||||
@@ -7,10 +7,9 @@ description: >
|
|||||||
inputs:
|
inputs:
|
||||||
token:
|
token:
|
||||||
description: >
|
description: >
|
||||||
Token used to authenticate release API calls. Defaults to the
|
Personal access token used to authenticate release API calls.
|
||||||
workflow token.
|
Required to support release updates across workflow boundaries.
|
||||||
required: false
|
required: true
|
||||||
default: ''
|
|
||||||
version:
|
version:
|
||||||
description: >
|
description: >
|
||||||
Semantic version to publish (with or without leading v). When omitted,
|
Semantic version to publish (with or without leading v). When omitted,
|
||||||
@@ -57,6 +56,7 @@ runs:
|
|||||||
normalized="${tag#v}"
|
normalized="${tag#v}"
|
||||||
else
|
else
|
||||||
echo "A version input is required when the workflow is not running from a tag push" >&2
|
echo "A version input is required when the workflow is not running from a tag push" >&2
|
||||||
|
echo "Provide version via input or ensure HEAD is at a tagged commit." >&2
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -65,7 +65,7 @@ runs:
|
|||||||
|
|
||||||
- name: Extract release notes
|
- name: Extract release notes
|
||||||
id: extract-notes
|
id: extract-notes
|
||||||
uses: ../run-vociferate
|
uses: ./run-vociferate
|
||||||
with:
|
with:
|
||||||
root: ${{ github.workspace }}
|
root: ${{ github.workspace }}
|
||||||
changelog: ${{ inputs.changelog }}
|
changelog: ${{ inputs.changelog }}
|
||||||
@@ -90,41 +90,66 @@ runs:
|
|||||||
id: create-release
|
id: create-release
|
||||||
shell: bash
|
shell: bash
|
||||||
env:
|
env:
|
||||||
TOKEN: ${{ inputs.token != '' && inputs.token || github.token }}
|
TOKEN: ${{ inputs.token }}
|
||||||
TAG_NAME: ${{ steps.resolve-version.outputs.tag }}
|
TAG_NAME: ${{ steps.resolve-version.outputs.tag }}
|
||||||
RELEASE_NOTES_FILE: ${{ steps.write-notes.outputs.notes_file }}
|
RELEASE_NOTES_FILE: ${{ steps.write-notes.outputs.notes_file }}
|
||||||
GITHUB_API_URL: ${{ github.api_url }}
|
GITHUB_API_URL: ${{ github.api_url }}
|
||||||
GITHUB_SERVER_URL: ${{ github.server_url }}
|
GITHUB_SERVER_URL: ${{ github.server_url }}
|
||||||
GITHUB_SHA: ${{ github.sha }}
|
|
||||||
GITHUB_REPOSITORY: ${{ github.repository }}
|
GITHUB_REPOSITORY: ${{ github.repository }}
|
||||||
run: |
|
run: |
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
|
parse_release_id() {
|
||||||
|
local json_file="$1"
|
||||||
|
|
||||||
|
if command -v python3 >/dev/null 2>&1; then
|
||||||
|
python3 -c 'import json, sys; payload = json.load(open(sys.argv[1], encoding="utf-8")); value = payload.get("id"); print(value if isinstance(value, int) else "")' "$json_file"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Fallback for environments without python3.
|
||||||
|
sed -n 's/.*"id"[[:space:]]*:[[:space:]]*\([0-9][0-9]*\).*/\1/p' "$json_file" | head -n 1
|
||||||
|
}
|
||||||
|
|
||||||
|
raw_token="$(printf '%s' "${TOKEN:-}" | sed 's/^[[:space:]]\+//; s/[[:space:]]\+$//')"
|
||||||
|
if [[ "$raw_token" =~ ^%\!t\(string=(.*)\)$ ]]; then
|
||||||
|
raw_token="${BASH_REMATCH[1]}"
|
||||||
|
fi
|
||||||
|
api_token="$(printf '%s' "$raw_token" | sed 's/^[[:space:]]\+//; s/[[:space:]]\+$//')"
|
||||||
|
|
||||||
|
if [[ -z "$api_token" ]]; then
|
||||||
|
echo "inputs.token is required (set to secrets.RELEASE_PAT)." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
release_notes="$(cat "$RELEASE_NOTES_FILE")"
|
release_notes="$(cat "$RELEASE_NOTES_FILE")"
|
||||||
escaped_release_notes="$(printf '%s' "$release_notes" | sed 's/\\/\\\\/g; s/"/\\"/g; :a;N;$!ba;s/\n/\\n/g')"
|
escaped_release_notes="$(printf '%s' "$release_notes" | sed 's/\\/\\\\/g; s/"/\\"/g; :a;N;$!ba;s/\n/\\n/g')"
|
||||||
release_api="${GITHUB_API_URL:-${GITHUB_SERVER_URL%/}/api/v1}/repos/${GITHUB_REPOSITORY}/releases"
|
release_api="${GITHUB_API_URL:-${GITHUB_SERVER_URL%/}/api/v1}/repos/${GITHUB_REPOSITORY}/releases"
|
||||||
release_by_tag_api="${release_api}/tags/${TAG_NAME}"
|
release_by_tag_api="${release_api}/tags/${TAG_NAME}"
|
||||||
|
|
||||||
status_code="$(curl -sS -o release-existing.json -w '%{http_code}' \
|
status_code="$(curl -sS -o release-existing.json -w '%{http_code}' \
|
||||||
-H "Authorization: token ${TOKEN}" \
|
-H "Authorization: token ${api_token}" \
|
||||||
-H "Content-Type: application/json" \
|
-H "Content-Type: application/json" \
|
||||||
"${release_by_tag_api}")"
|
"${release_by_tag_api}")"
|
||||||
|
|
||||||
if [[ "$status_code" == "200" ]]; then
|
if [[ "$status_code" == "200" ]]; then
|
||||||
existing_release_id="$(sed -n 's/.*"id"[[:space:]]*:[[:space:]]*\([0-9][0-9]*\).*/\1/p' release-existing.json | head -n 1)"
|
existing_release_id="$(parse_release_id release-existing.json)"
|
||||||
if [[ -z "$existing_release_id" ]]; then
|
if [[ -z "$existing_release_id" ]]; then
|
||||||
echo "Failed to parse existing release id for ${TAG_NAME}" >&2
|
echo "Failed to parse existing release id for ${TAG_NAME}" >&2
|
||||||
cat release-existing.json >&2
|
cat release-existing.json >&2
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
curl --fail-with-body \
|
if ! curl --fail-with-body \
|
||||||
-X PATCH \
|
-X PATCH \
|
||||||
-H "Authorization: token ${TOKEN}" \
|
-H "Authorization: token ${api_token}" \
|
||||||
-H "Content-Type: application/json" \
|
-H "Content-Type: application/json" \
|
||||||
"${release_api}/${existing_release_id}" \
|
"${release_api}/${existing_release_id}" \
|
||||||
--data "{\"tag_name\":\"${TAG_NAME}\",\"target\":\"${GITHUB_SHA}\",\"name\":\"${TAG_NAME}\",\"body\":\"${escaped_release_notes}\",\"draft\":false,\"prerelease\":false}" \
|
--data "{\"tag_name\":\"${TAG_NAME}\",\"name\":\"${TAG_NAME}\",\"body\":\"${escaped_release_notes}\",\"draft\":false,\"prerelease\":false}" \
|
||||||
--output release.json
|
--output release.json; then
|
||||||
|
cat release.json >&2 || true
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
echo "id=$existing_release_id" >> "$GITHUB_OUTPUT"
|
echo "id=$existing_release_id" >> "$GITHUB_OUTPUT"
|
||||||
elif [[ "$status_code" != "404" ]]; then
|
elif [[ "$status_code" != "404" ]]; then
|
||||||
@@ -132,15 +157,18 @@ runs:
|
|||||||
cat release-existing.json >&2
|
cat release-existing.json >&2
|
||||||
exit 1
|
exit 1
|
||||||
else
|
else
|
||||||
curl --fail-with-body \
|
if ! curl --fail-with-body \
|
||||||
-X POST \
|
-X POST \
|
||||||
-H "Authorization: token ${TOKEN}" \
|
-H "Authorization: token ${api_token}" \
|
||||||
-H "Content-Type: application/json" \
|
-H "Content-Type: application/json" \
|
||||||
"${release_api}" \
|
"${release_api}" \
|
||||||
--data "{\"tag_name\":\"${TAG_NAME}\",\"target\":\"${GITHUB_SHA}\",\"name\":\"${TAG_NAME}\",\"body\":\"${escaped_release_notes}\",\"draft\":false,\"prerelease\":false}" \
|
--data "{\"tag_name\":\"${TAG_NAME}\",\"name\":\"${TAG_NAME}\",\"body\":\"${escaped_release_notes}\",\"draft\":false,\"prerelease\":false}" \
|
||||||
--output release.json
|
--output release.json; then
|
||||||
|
cat release.json >&2 || true
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
release_id="$(sed -n 's/.*"id"[[:space:]]*:[[:space:]]*\([0-9][0-9]*\).*/\1/p' release.json | head -n 1)"
|
release_id="$(parse_release_id release.json)"
|
||||||
if [[ -z "$release_id" ]]; then
|
if [[ -z "$release_id" ]]; then
|
||||||
echo "Failed to parse release id from API response" >&2
|
echo "Failed to parse release id from API response" >&2
|
||||||
cat release.json >&2
|
cat release.json >&2
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
1.0.2
|
1.1.0
|
||||||
|
|||||||
@@ -63,35 +63,198 @@ runs:
|
|||||||
printf 'use_binary=false\n' >> "$GITHUB_OUTPUT"
|
printf 'use_binary=false\n' >> "$GITHUB_OUTPUT"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
- name: Resolve binary metadata
|
||||||
|
id: resolve-binary
|
||||||
|
if: steps.resolve-runtime.outputs.use_binary == 'true'
|
||||||
|
shell: bash
|
||||||
|
env:
|
||||||
|
ACTION_REF: ${{ github.action_ref }}
|
||||||
|
ACTION_REPOSITORY: ${{ github.action_repository }}
|
||||||
|
CACHE_TOKEN: ${{ env.VOCIFERATE_CACHE_TOKEN }}
|
||||||
|
SERVER_URL: ${{ github.server_url }}
|
||||||
|
RUNNER_ARCH: ${{ runner.arch }}
|
||||||
|
RUNNER_TEMP: ${{ runner.temp }}
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
if [[ "$ACTION_REF" != v* ]]; then
|
||||||
|
echo "run-vociferate binary path requires github.action_ref to be a release tag" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
case "$RUNNER_ARCH" in
|
||||||
|
X64)
|
||||||
|
arch="amd64"
|
||||||
|
;;
|
||||||
|
ARM64)
|
||||||
|
arch="arm64"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Unsupported runner architecture: $RUNNER_ARCH" >&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
release_tag="$ACTION_REF"
|
||||||
|
normalized_version="${release_tag#v}"
|
||||||
|
asset_name="vociferate_${normalized_version}_linux_${arch}"
|
||||||
|
cache_dir="${RUNNER_TEMP}/vociferate/${release_tag}/linux-${arch}"
|
||||||
|
binary_path="${cache_dir}/vociferate"
|
||||||
|
asset_url="${SERVER_URL}/aether/vociferate/releases/download/${release_tag}/${asset_name}"
|
||||||
|
|
||||||
|
provided_cache_token="$(printf '%s' "${CACHE_TOKEN:-}" | sed 's/^[[:space:]]\+//; s/[[:space:]]\+$//')"
|
||||||
|
if [[ -n "$provided_cache_token" ]]; then
|
||||||
|
cache_token="$provided_cache_token"
|
||||||
|
else
|
||||||
|
cache_token="${ACTION_REPOSITORY:-aether/vociferate}-${release_tag}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
mkdir -p "$cache_dir"
|
||||||
|
|
||||||
|
printf 'cache_token=%s\n' "$cache_token" >> "$GITHUB_OUTPUT"
|
||||||
|
printf 'cache_dir=%s\n' "$cache_dir" >> "$GITHUB_OUTPUT"
|
||||||
|
printf 'binary_path=%s\n' "$binary_path" >> "$GITHUB_OUTPUT"
|
||||||
|
printf 'asset_url=%s\n' "$asset_url" >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
|
- name: Restore cached binary
|
||||||
|
id: cache-vociferate
|
||||||
|
if: steps.resolve-runtime.outputs.use_binary == 'true'
|
||||||
|
uses: actions/cache@v4
|
||||||
|
with:
|
||||||
|
path: ${{ steps.resolve-binary.outputs.cache_dir }}
|
||||||
|
key: vociferate-${{ steps.resolve-binary.outputs.cache_token }}-linux-${{ runner.arch }}
|
||||||
|
|
||||||
|
- name: Download binary
|
||||||
|
if: steps.resolve-runtime.outputs.use_binary == 'true' && steps.cache-vociferate.outputs.cache-hit != 'true'
|
||||||
|
shell: bash
|
||||||
|
env:
|
||||||
|
TOKEN: ${{ github.token }}
|
||||||
|
ASSET_URL: ${{ steps.resolve-binary.outputs.asset_url }}
|
||||||
|
BINARY_PATH: ${{ steps.resolve-binary.outputs.binary_path }}
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
curl --fail --location \
|
||||||
|
-H "Authorization: token ${TOKEN}" \
|
||||||
|
-o "$BINARY_PATH" \
|
||||||
|
"$ASSET_URL"
|
||||||
|
chmod +x "$BINARY_PATH"
|
||||||
|
|
||||||
- name: Run binary
|
- name: Run binary
|
||||||
id: run-binary
|
id: run-binary
|
||||||
if: steps.resolve-runtime.outputs.use_binary == 'true'
|
if: steps.resolve-runtime.outputs.use_binary == 'true'
|
||||||
uses: ./binary
|
shell: bash
|
||||||
with:
|
env:
|
||||||
root: ${{ inputs.root }}
|
VOCIFERATE_BIN: ${{ steps.resolve-binary.outputs.binary_path }}
|
||||||
version-file: ${{ inputs.version-file }}
|
ROOT: ${{ inputs.root }}
|
||||||
version-pattern: ${{ inputs.version-pattern }}
|
VERSION_FILE: ${{ inputs.version-file }}
|
||||||
changelog: ${{ inputs.changelog }}
|
VERSION_PATTERN: ${{ inputs.version-pattern }}
|
||||||
version: ${{ inputs.version }}
|
CHANGELOG: ${{ inputs.changelog }}
|
||||||
date: ${{ inputs.date }}
|
VERSION: ${{ inputs.version }}
|
||||||
recommend: ${{ inputs.recommend }}
|
DATE: ${{ inputs.date }}
|
||||||
print-unreleased: ${{ inputs.print-unreleased }}
|
RECOMMEND: ${{ inputs.recommend }}
|
||||||
print-release-notes: ${{ inputs.print-release-notes }}
|
PRINT_UNRELEASED: ${{ inputs.print-unreleased }}
|
||||||
|
PRINT_RELEASE_NOTES: ${{ inputs.print-release-notes }}
|
||||||
|
VOCIFERATE_REPOSITORY_URL: ${{ vars.VOCIFERATE_REPOSITORY_URL }}
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
command=("$VOCIFERATE_BIN" --root "$ROOT")
|
||||||
|
if [[ -n "$VERSION_FILE" ]]; then
|
||||||
|
command+=(--version-file "$VERSION_FILE")
|
||||||
|
fi
|
||||||
|
if [[ -n "$VERSION_PATTERN" ]]; then
|
||||||
|
command+=(--version-pattern "$VERSION_PATTERN")
|
||||||
|
fi
|
||||||
|
if [[ -n "$CHANGELOG" ]]; then
|
||||||
|
command+=(--changelog "$CHANGELOG")
|
||||||
|
fi
|
||||||
|
if [[ -n "$VERSION" ]]; then
|
||||||
|
command+=(--version "$VERSION")
|
||||||
|
fi
|
||||||
|
if [[ -n "$DATE" ]]; then
|
||||||
|
command+=(--date "$DATE")
|
||||||
|
fi
|
||||||
|
if [[ "$RECOMMEND" == 'true' ]]; then
|
||||||
|
command+=(--recommend)
|
||||||
|
fi
|
||||||
|
if [[ "$PRINT_UNRELEASED" == 'true' ]]; then
|
||||||
|
command+=(--print-unreleased)
|
||||||
|
fi
|
||||||
|
if [[ "$PRINT_RELEASE_NOTES" == 'true' ]]; then
|
||||||
|
command+=(--print-release-notes)
|
||||||
|
fi
|
||||||
|
|
||||||
|
stdout_file="$(mktemp)"
|
||||||
|
trap 'rm -f "$stdout_file"' EXIT
|
||||||
|
"${command[@]}" > "$stdout_file"
|
||||||
|
|
||||||
|
delimiter="EOF_STDOUT"
|
||||||
|
printf 'stdout<<%s\n' "$delimiter" >> "$GITHUB_OUTPUT"
|
||||||
|
cat "$stdout_file" >> "$GITHUB_OUTPUT"
|
||||||
|
printf '%s\n' "$delimiter" >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
- name: Run source
|
- name: Run source
|
||||||
id: run-code
|
id: run-code
|
||||||
if: steps.resolve-runtime.outputs.use_binary != 'true'
|
if: steps.resolve-runtime.outputs.use_binary != 'true'
|
||||||
uses: ./code
|
shell: bash
|
||||||
with:
|
env:
|
||||||
root: ${{ inputs.root }}
|
ROOT: ${{ inputs.root }}
|
||||||
version-file: ${{ inputs.version-file }}
|
VERSION_FILE: ${{ inputs.version-file }}
|
||||||
version-pattern: ${{ inputs.version-pattern }}
|
VERSION_PATTERN: ${{ inputs.version-pattern }}
|
||||||
changelog: ${{ inputs.changelog }}
|
CHANGELOG: ${{ inputs.changelog }}
|
||||||
version: ${{ inputs.version }}
|
VERSION: ${{ inputs.version }}
|
||||||
date: ${{ inputs.date }}
|
DATE: ${{ inputs.date }}
|
||||||
recommend: ${{ inputs.recommend }}
|
RECOMMEND: ${{ inputs.recommend }}
|
||||||
print-unreleased: ${{ inputs.print-unreleased }}
|
PRINT_UNRELEASED: ${{ inputs.print-unreleased }}
|
||||||
print-release-notes: ${{ inputs.print-release-notes }}
|
PRINT_RELEASE_NOTES: ${{ inputs.print-release-notes }}
|
||||||
|
VOCIFERATE_REPOSITORY_URL: ${{ vars.VOCIFERATE_REPOSITORY_URL }}
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
source_root="$GITHUB_ACTION_PATH"
|
||||||
|
while [[ ! -f "$source_root/go.mod" ]] && [[ "$source_root" != "/" ]]; do
|
||||||
|
source_root="$(realpath "$source_root/..")"
|
||||||
|
done
|
||||||
|
if [[ ! -f "$source_root/go.mod" ]]; then
|
||||||
|
echo "Could not locate Go module root from $GITHUB_ACTION_PATH" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
command=(go run ./cmd/vociferate --root "$ROOT")
|
||||||
|
if [[ -n "$VERSION_FILE" ]]; then
|
||||||
|
command+=(--version-file "$VERSION_FILE")
|
||||||
|
fi
|
||||||
|
if [[ -n "$VERSION_PATTERN" ]]; then
|
||||||
|
command+=(--version-pattern "$VERSION_PATTERN")
|
||||||
|
fi
|
||||||
|
if [[ -n "$CHANGELOG" ]]; then
|
||||||
|
command+=(--changelog "$CHANGELOG")
|
||||||
|
fi
|
||||||
|
if [[ -n "$VERSION" ]]; then
|
||||||
|
command+=(--version "$VERSION")
|
||||||
|
fi
|
||||||
|
if [[ -n "$DATE" ]]; then
|
||||||
|
command+=(--date "$DATE")
|
||||||
|
fi
|
||||||
|
if [[ "$RECOMMEND" == 'true' ]]; then
|
||||||
|
command+=(--recommend)
|
||||||
|
fi
|
||||||
|
if [[ "$PRINT_UNRELEASED" == 'true' ]]; then
|
||||||
|
command+=(--print-unreleased)
|
||||||
|
fi
|
||||||
|
if [[ "$PRINT_RELEASE_NOTES" == 'true' ]]; then
|
||||||
|
command+=(--print-release-notes)
|
||||||
|
fi
|
||||||
|
|
||||||
|
stdout_file="$(mktemp)"
|
||||||
|
trap 'rm -f "$stdout_file"' EXIT
|
||||||
|
(cd "$source_root" && "${command[@]}") > "$stdout_file"
|
||||||
|
|
||||||
|
delimiter="EOF_STDOUT"
|
||||||
|
printf 'stdout<<%s\n' "$delimiter" >> "$GITHUB_OUTPUT"
|
||||||
|
cat "$stdout_file" >> "$GITHUB_OUTPUT"
|
||||||
|
printf '%s\n' "$delimiter" >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
- name: Finalize stdout
|
- name: Finalize stdout
|
||||||
id: finalize
|
id: finalize
|
||||||
|
|||||||
@@ -1,176 +0,0 @@
|
|||||||
name: vociferate/run-vociferate-binary
|
|
||||||
description: Execute vociferate through a released binary.
|
|
||||||
|
|
||||||
inputs:
|
|
||||||
root:
|
|
||||||
description: Repository root to pass to vociferate.
|
|
||||||
required: true
|
|
||||||
version-file:
|
|
||||||
description: Optional version file path.
|
|
||||||
required: false
|
|
||||||
default: ''
|
|
||||||
version-pattern:
|
|
||||||
description: Optional version pattern.
|
|
||||||
required: false
|
|
||||||
default: ''
|
|
||||||
changelog:
|
|
||||||
description: Optional changelog path.
|
|
||||||
required: false
|
|
||||||
default: ''
|
|
||||||
version:
|
|
||||||
description: Optional version argument.
|
|
||||||
required: false
|
|
||||||
default: ''
|
|
||||||
date:
|
|
||||||
description: Optional date argument.
|
|
||||||
required: false
|
|
||||||
default: ''
|
|
||||||
recommend:
|
|
||||||
description: Whether to run vociferate with --recommend.
|
|
||||||
required: false
|
|
||||||
default: 'false'
|
|
||||||
print-unreleased:
|
|
||||||
description: Whether to print the Unreleased body.
|
|
||||||
required: false
|
|
||||||
default: 'false'
|
|
||||||
print-release-notes:
|
|
||||||
description: Whether to print the release notes section for version.
|
|
||||||
required: false
|
|
||||||
default: 'false'
|
|
||||||
|
|
||||||
outputs:
|
|
||||||
stdout:
|
|
||||||
description: Captured stdout from the vociferate invocation.
|
|
||||||
value: ${{ steps.run.outputs.stdout }}
|
|
||||||
|
|
||||||
runs:
|
|
||||||
using: composite
|
|
||||||
steps:
|
|
||||||
- name: Resolve binary metadata
|
|
||||||
id: resolve-binary
|
|
||||||
shell: bash
|
|
||||||
env:
|
|
||||||
ACTION_REF: ${{ github.action_ref }}
|
|
||||||
ACTION_REPOSITORY: ${{ github.action_repository }}
|
|
||||||
CACHE_TOKEN: ${{ env.VOCIFERATE_CACHE_TOKEN }}
|
|
||||||
SERVER_URL: ${{ github.server_url }}
|
|
||||||
RUNNER_ARCH: ${{ runner.arch }}
|
|
||||||
RUNNER_TEMP: ${{ runner.temp }}
|
|
||||||
run: |
|
|
||||||
set -euo pipefail
|
|
||||||
|
|
||||||
if [[ "$ACTION_REF" != v* ]]; then
|
|
||||||
echo "run-vociferate.binary requires github.action_ref to be a release tag" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
case "$RUNNER_ARCH" in
|
|
||||||
X64)
|
|
||||||
arch="amd64"
|
|
||||||
;;
|
|
||||||
ARM64)
|
|
||||||
arch="arm64"
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
echo "Unsupported runner architecture: $RUNNER_ARCH" >&2
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
release_tag="$ACTION_REF"
|
|
||||||
normalized_version="${release_tag#v}"
|
|
||||||
asset_name="vociferate_${normalized_version}_linux_${arch}"
|
|
||||||
cache_dir="${RUNNER_TEMP}/vociferate/${release_tag}/linux-${arch}"
|
|
||||||
binary_path="${cache_dir}/vociferate"
|
|
||||||
asset_url="${SERVER_URL}/aether/vociferate/releases/download/${release_tag}/${asset_name}"
|
|
||||||
|
|
||||||
provided_cache_token="$(printf '%s' "${CACHE_TOKEN:-}" | sed 's/^[[:space:]]\+//; s/[[:space:]]\+$//')"
|
|
||||||
if [[ -n "$provided_cache_token" ]]; then
|
|
||||||
cache_token="$provided_cache_token"
|
|
||||||
else
|
|
||||||
cache_token="${ACTION_REPOSITORY:-aether/vociferate}-${release_tag}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
mkdir -p "$cache_dir"
|
|
||||||
|
|
||||||
printf 'cache_token=%s\n' "$cache_token" >> "$GITHUB_OUTPUT"
|
|
||||||
printf 'cache_dir=%s\n' "$cache_dir" >> "$GITHUB_OUTPUT"
|
|
||||||
printf 'binary_path=%s\n' "$binary_path" >> "$GITHUB_OUTPUT"
|
|
||||||
printf 'asset_url=%s\n' "$asset_url" >> "$GITHUB_OUTPUT"
|
|
||||||
|
|
||||||
- name: Restore cached binary
|
|
||||||
id: cache-vociferate
|
|
||||||
uses: actions/cache@v4
|
|
||||||
with:
|
|
||||||
path: ${{ steps.resolve-binary.outputs.cache_dir }}
|
|
||||||
key: vociferate-${{ steps.resolve-binary.outputs.cache_token }}-linux-${{ runner.arch }}
|
|
||||||
|
|
||||||
- name: Download binary
|
|
||||||
if: steps.cache-vociferate.outputs.cache-hit != 'true'
|
|
||||||
shell: bash
|
|
||||||
env:
|
|
||||||
TOKEN: ${{ github.token }}
|
|
||||||
ASSET_URL: ${{ steps.resolve-binary.outputs.asset_url }}
|
|
||||||
BINARY_PATH: ${{ steps.resolve-binary.outputs.binary_path }}
|
|
||||||
run: |
|
|
||||||
set -euo pipefail
|
|
||||||
|
|
||||||
curl --fail --location \
|
|
||||||
-H "Authorization: token ${TOKEN}" \
|
|
||||||
-o "$BINARY_PATH" \
|
|
||||||
"$ASSET_URL"
|
|
||||||
chmod +x "$BINARY_PATH"
|
|
||||||
|
|
||||||
- name: Run binary
|
|
||||||
id: run
|
|
||||||
shell: bash
|
|
||||||
env:
|
|
||||||
VOCIFERATE_BIN: ${{ steps.resolve-binary.outputs.binary_path }}
|
|
||||||
ROOT: ${{ inputs.root }}
|
|
||||||
VERSION_FILE: ${{ inputs.version-file }}
|
|
||||||
VERSION_PATTERN: ${{ inputs.version-pattern }}
|
|
||||||
CHANGELOG: ${{ inputs.changelog }}
|
|
||||||
VERSION: ${{ inputs.version }}
|
|
||||||
DATE: ${{ inputs.date }}
|
|
||||||
RECOMMEND: ${{ inputs.recommend }}
|
|
||||||
PRINT_UNRELEASED: ${{ inputs.print-unreleased }}
|
|
||||||
PRINT_RELEASE_NOTES: ${{ inputs.print-release-notes }}
|
|
||||||
VOCIFERATE_REPOSITORY_URL: ${{ vars.VOCIFERATE_REPOSITORY_URL }}
|
|
||||||
run: |
|
|
||||||
set -euo pipefail
|
|
||||||
|
|
||||||
command=("$VOCIFERATE_BIN" --root "$ROOT")
|
|
||||||
|
|
||||||
if [[ -n "$VERSION_FILE" ]]; then
|
|
||||||
command+=(--version-file "$VERSION_FILE")
|
|
||||||
fi
|
|
||||||
if [[ -n "$VERSION_PATTERN" ]]; then
|
|
||||||
command+=(--version-pattern "$VERSION_PATTERN")
|
|
||||||
fi
|
|
||||||
if [[ -n "$CHANGELOG" ]]; then
|
|
||||||
command+=(--changelog "$CHANGELOG")
|
|
||||||
fi
|
|
||||||
if [[ -n "$VERSION" ]]; then
|
|
||||||
command+=(--version "$VERSION")
|
|
||||||
fi
|
|
||||||
if [[ -n "$DATE" ]]; then
|
|
||||||
command+=(--date "$DATE")
|
|
||||||
fi
|
|
||||||
if [[ "$RECOMMEND" == 'true' ]]; then
|
|
||||||
command+=(--recommend)
|
|
||||||
fi
|
|
||||||
if [[ "$PRINT_UNRELEASED" == 'true' ]]; then
|
|
||||||
command+=(--print-unreleased)
|
|
||||||
fi
|
|
||||||
if [[ "$PRINT_RELEASE_NOTES" == 'true' ]]; then
|
|
||||||
command+=(--print-release-notes)
|
|
||||||
fi
|
|
||||||
|
|
||||||
stdout_file="$(mktemp)"
|
|
||||||
trap 'rm -f "$stdout_file"' EXIT
|
|
||||||
"${command[@]}" > "$stdout_file"
|
|
||||||
|
|
||||||
delimiter="EOF_STDOUT"
|
|
||||||
printf 'stdout<<%s\n' "$delimiter" >> "$GITHUB_OUTPUT"
|
|
||||||
cat "$stdout_file" >> "$GITHUB_OUTPUT"
|
|
||||||
printf '%s\n' "$delimiter" >> "$GITHUB_OUTPUT"
|
|
||||||
@@ -1,125 +0,0 @@
|
|||||||
name: vociferate/run-vociferate-code
|
|
||||||
description: Execute vociferate from the checked-out Go source.
|
|
||||||
|
|
||||||
inputs:
|
|
||||||
root:
|
|
||||||
description: Repository root to pass to vociferate.
|
|
||||||
required: true
|
|
||||||
version-file:
|
|
||||||
description: Optional version file path.
|
|
||||||
required: false
|
|
||||||
default: ''
|
|
||||||
version-pattern:
|
|
||||||
description: Optional version pattern.
|
|
||||||
required: false
|
|
||||||
default: ''
|
|
||||||
changelog:
|
|
||||||
description: Optional changelog path.
|
|
||||||
required: false
|
|
||||||
default: ''
|
|
||||||
version:
|
|
||||||
description: Optional version argument.
|
|
||||||
required: false
|
|
||||||
default: ''
|
|
||||||
date:
|
|
||||||
description: Optional date argument.
|
|
||||||
required: false
|
|
||||||
default: ''
|
|
||||||
recommend:
|
|
||||||
description: Whether to run vociferate with --recommend.
|
|
||||||
required: false
|
|
||||||
default: 'false'
|
|
||||||
print-unreleased:
|
|
||||||
description: Whether to print the Unreleased body.
|
|
||||||
required: false
|
|
||||||
default: 'false'
|
|
||||||
print-release-notes:
|
|
||||||
description: Whether to print the release notes section for version.
|
|
||||||
required: false
|
|
||||||
default: 'false'
|
|
||||||
|
|
||||||
outputs:
|
|
||||||
stdout:
|
|
||||||
description: Captured stdout from the vociferate invocation.
|
|
||||||
value: ${{ steps.run.outputs.stdout }}
|
|
||||||
|
|
||||||
runs:
|
|
||||||
using: composite
|
|
||||||
steps:
|
|
||||||
- name: Resolve source root
|
|
||||||
id: resolve-source
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
set -euo pipefail
|
|
||||||
|
|
||||||
source_root="$GITHUB_ACTION_PATH"
|
|
||||||
while [[ ! -f "$source_root/go.mod" ]] && [[ "$source_root" != "/" ]]; do
|
|
||||||
source_root="$(realpath "$source_root/..")"
|
|
||||||
done
|
|
||||||
if [[ ! -f "$source_root/go.mod" ]]; then
|
|
||||||
echo "Could not locate Go module root from $GITHUB_ACTION_PATH" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
printf 'source_root=%s\n' "$source_root" >> "$GITHUB_OUTPUT"
|
|
||||||
|
|
||||||
- name: Setup Go
|
|
||||||
uses: actions/setup-go@v5
|
|
||||||
with:
|
|
||||||
go-version: '1.26.1'
|
|
||||||
cache: true
|
|
||||||
cache-dependency-path: ${{ steps.resolve-source.outputs.source_root }}/go.sum
|
|
||||||
|
|
||||||
- name: Run source
|
|
||||||
id: run
|
|
||||||
shell: bash
|
|
||||||
working-directory: ${{ steps.resolve-source.outputs.source_root }}
|
|
||||||
env:
|
|
||||||
ROOT: ${{ inputs.root }}
|
|
||||||
VERSION_FILE: ${{ inputs.version-file }}
|
|
||||||
VERSION_PATTERN: ${{ inputs.version-pattern }}
|
|
||||||
CHANGELOG: ${{ inputs.changelog }}
|
|
||||||
VERSION: ${{ inputs.version }}
|
|
||||||
DATE: ${{ inputs.date }}
|
|
||||||
RECOMMEND: ${{ inputs.recommend }}
|
|
||||||
PRINT_UNRELEASED: ${{ inputs.print-unreleased }}
|
|
||||||
PRINT_RELEASE_NOTES: ${{ inputs.print-release-notes }}
|
|
||||||
VOCIFERATE_REPOSITORY_URL: ${{ vars.VOCIFERATE_REPOSITORY_URL }}
|
|
||||||
run: |
|
|
||||||
set -euo pipefail
|
|
||||||
|
|
||||||
command=(go run ./cmd/vociferate --root "$ROOT")
|
|
||||||
|
|
||||||
if [[ -n "$VERSION_FILE" ]]; then
|
|
||||||
command+=(--version-file "$VERSION_FILE")
|
|
||||||
fi
|
|
||||||
if [[ -n "$VERSION_PATTERN" ]]; then
|
|
||||||
command+=(--version-pattern "$VERSION_PATTERN")
|
|
||||||
fi
|
|
||||||
if [[ -n "$CHANGELOG" ]]; then
|
|
||||||
command+=(--changelog "$CHANGELOG")
|
|
||||||
fi
|
|
||||||
if [[ -n "$VERSION" ]]; then
|
|
||||||
command+=(--version "$VERSION")
|
|
||||||
fi
|
|
||||||
if [[ -n "$DATE" ]]; then
|
|
||||||
command+=(--date "$DATE")
|
|
||||||
fi
|
|
||||||
if [[ "$RECOMMEND" == 'true' ]]; then
|
|
||||||
command+=(--recommend)
|
|
||||||
fi
|
|
||||||
if [[ "$PRINT_UNRELEASED" == 'true' ]]; then
|
|
||||||
command+=(--print-unreleased)
|
|
||||||
fi
|
|
||||||
if [[ "$PRINT_RELEASE_NOTES" == 'true' ]]; then
|
|
||||||
command+=(--print-release-notes)
|
|
||||||
fi
|
|
||||||
|
|
||||||
stdout_file="$(mktemp)"
|
|
||||||
trap 'rm -f "$stdout_file"' EXIT
|
|
||||||
"${command[@]}" > "$stdout_file"
|
|
||||||
|
|
||||||
delimiter="EOF_STDOUT"
|
|
||||||
printf 'stdout<<%s\n' "$delimiter" >> "$GITHUB_OUTPUT"
|
|
||||||
cat "$stdout_file" >> "$GITHUB_OUTPUT"
|
|
||||||
printf '%s\n' "$delimiter" >> "$GITHUB_OUTPUT"
|
|
||||||
Reference in New Issue
Block a user