diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..5bc4c41 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,88 @@ +name: Release + +# Version tags only. Pull requests do not publish binaries. +on: + push: + tags: + - "v*.*.*" + +permissions: + contents: write + +jobs: + binaries: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Set up Go + uses: actions/setup-go@v4 + with: + go-version: '1.24' + + - name: Build release binaries + env: + TAG: ${{ github.ref_name }} + run: | + set -euo pipefail + if [[ ! "$TAG" =~ ^v[0-9]+\.[0-9]+\.[0-9]+([.+-][0-9A-Za-z]+)*$ ]]; then + printf 'refusing tag %q; expected vMAJOR.MINOR.PATCH\n' "$TAG" >&2 + exit 1 + fi + mkdir -p dist + targets=( + linux/amd64 + linux/arm64 + darwin/amd64 + darwin/arm64 + ) + for target in "${targets[@]}"; do + goos="${target%/*}" + goarch="${target#*/}" + out="dist/validgen_${TAG}_${goos}_${goarch}" + CGO_ENABLED=0 GOOS="$goos" GOARCH="$goarch" \ + go build -trimpath -ldflags='-s -w -buildid=' -o "$out" . + done + ( + cd dist + sha256sum validgen_* | LC_ALL=C sort -k 2 > SHA256SUMS + ) + mapfile -t bins < <(find dist -maxdepth 1 -type f -name "validgen_${TAG}_*" | LC_ALL=C sort) + if (( ${#bins[@]} != 4 )); then + printf 'expected 4 binaries, found %s\n' "${#bins[@]}" >&2 + printf '%s\n' "${bins[@]}" >&2 + exit 1 + fi + + - name: Publish GitHub release assets + env: + GH_TOKEN: ${{ github.token }} + TAG: ${{ github.ref_name }} + run: | + set -euo pipefail + if [[ ! "$TAG" =~ ^v[0-9]+\.[0-9]+\.[0-9]+([.+-][0-9A-Za-z]+)*$ ]]; then + printf 'refusing tag %q; expected vMAJOR.MINOR.PATCH\n' "$TAG" >&2 + exit 1 + fi + assets=( + "dist/validgen_${TAG}_linux_amd64" + "dist/validgen_${TAG}_linux_arm64" + "dist/validgen_${TAG}_darwin_amd64" + "dist/validgen_${TAG}_darwin_arm64" + dist/SHA256SUMS + ) + for asset in "${assets[@]}"; do + if [[ ! -f "$asset" ]]; then + printf 'missing asset %q\n' "$asset" >&2 + exit 1 + fi + done + if gh release view "$TAG" >/dev/null 2>&1; then + gh release upload "$TAG" --clobber "${assets[@]}" + else + args=(release create "$TAG" "${assets[@]}" --verify-tag --title "$TAG" --generate-notes) + if [[ "$TAG" == *-* ]]; then + args+=(--prerelease) + fi + gh "${args[@]}" + fi diff --git a/README.md b/README.md index d6bdcf2..156c6b9 100644 --- a/README.md +++ b/README.md @@ -33,6 +33,20 @@ make build After that the executable will be in `bin/validgen`. +## Releases + +Push a tag named `vMAJOR.MINOR.PATCH`, with an optional pre-release suffix such as `-rc.1`. That tag push runs [Release](.github/workflows/release.yml) on a GitHub-hosted runner. The workflow cross-compiles ValidGen with `CGO_ENABLED=0` and attaches the binaries to the GitHub release for that tag. Pull requests do not publish releases. + +The release assets are: + +- `validgen_v1.2.3_linux_amd64` +- `validgen_v1.2.3_linux_arm64` +- `validgen_v1.2.3_darwin_amd64` +- `validgen_v1.2.3_darwin_arm64` +- `SHA256SUMS` + +`amd64` is the Intel 64-bit build. `arm64` is the Arm 64-bit build. + ## Optional JSON unmarshaling By default ValidGen only generates `TValidate` functions. Pass `-unmarshal-json` to also generate `encoding/json.Unmarshaler` methods that decode with an alias (to avoid recursion) and then validate: