#!/usr/bin/env fish function __release_fork_usage echo "Usage: release-fork.fish [--from ] [--only ] [--help] Stages (run in order): tag Compute next fork tag, push branch, create and push tag build Cross-compile for all release targets pack Compress Linux binaries with UPX upload Upload artifacts via release(1) Flags: --from Start at this stage and continue through the rest --only Run just this one stage --help, -h Show this help With no flags, all stages run in order (tag → build → pack → upload). Examples: ./release-fork.fish Full release ./release-fork.fish --from build Rebuild, pack, and upload (skip tagging) ./release-fork.fish --only build Just cross-compile ./release-fork.fish --only upload Re-upload existing dist/ artifacts" end set -l targets \ linux/amd64 \ linux/arm64 \ darwin/amd64 \ darwin/arm64 \ windows/amd64 \ freebsd/amd64 # UPX 5.x dropped macOS support; windows/amd64 is PE32 only and # freebsd/amd64 is ELF32 only, so only Linux targets are packed. set -l pack_targets \ linux-amd64 \ linux-arm64 # Global so __should_run can see them. Prefixed to avoid collisions. set -g __rf_stages tag build pack upload set -g __rf_from "" set -g __rf_only "" # --- Parse flags --- set -l i 1 while test $i -le (count $argv) switch $argv[$i] case --from set i (math $i + 1) set -g __rf_from $argv[$i] case --only set i (math $i + 1) set -g __rf_only $argv[$i] case --help -h __release_fork_usage exit 0 case '*' echo "Error: unknown flag '$argv[$i]'" >&2 __release_fork_usage >&2 exit 1 end set i (math $i + 1) end if test -n "$__rf_from" -a -n "$__rf_only" echo "Error: --from and --only are mutually exclusive" >&2 exit 1 end if test -n "$__rf_from"; and not contains -- "$__rf_from" $__rf_stages echo "Error: unknown stage '$__rf_from' (valid: $__rf_stages)" >&2 exit 1 end if test -n "$__rf_only"; and not contains -- "$__rf_only" $__rf_stages echo "Error: unknown stage '$__rf_only' (valid: $__rf_stages)" >&2 exit 1 end # --- Determine which stages to run --- # Returns 0 if the given stage should execute, 1 otherwise. function __should_run -a stage if test -n "$__rf_only" test "$stage" = "$__rf_only" return end if test -z "$__rf_from" return 0 end # Walk the stage list; once we reach __rf_from, every subsequent # stage (including __rf_from itself) should run. set -l reached 0 for s in $__rf_stages if test "$s" = "$__rf_from" set reached 1 end if test $reached -eq 1 -a "$s" = "$stage" return 0 end end return 1 end # --- Resolve tag --- # # When skipping the tag stage we still need a tag for filenames and # ldflags, so fall back to git describe. set -l tag if __should_run tag # --- Guards --- set -l branch (git symbolic-ref --short HEAD) if test "$branch" != dev echo "Error: not on dev branch (on $branch)" >&2 exit 1 end if test (git status --porcelain=2 | wc -l) -ne 0 echo "Error: git working tree is dirty" >&2 exit 1 end # --- Fetch tags --- git tag -d nightly 2>/dev/null; or true git fetch upstream --tags # --- Compute next fork tag --- set -l upstream_ver (git tag -l "v*" | grep -v -- '-fork\.' | sort -V | tail -1; or echo v0.0.0) set -l existing (git tag -l "$upstream_ver-fork.*" | wc -l | string trim) set -l next_num (math $existing + 1) set tag "$upstream_ver-fork.$next_num" # --- Confirm creation --- read -P "Create fork release $tag? [y/N] " confirm if test "$confirm" != y -a "$confirm" != Y echo Aborted. exit 0 end # --- Push branch (force because we amended) --- git push --force-with-lease; or begin echo "Error: branch push failed" >&2 exit 1 end # --- Tag and push --- git tag -a $tag; or begin echo "Error: tagging failed" >&2 exit 1 end git push soft $tag; or begin echo "Error: tag push failed — deleting local tag" >&2 git tag -d $tag 2>/dev/null exit 1 end echo "Released $tag" else set tag (git describe --tags --always 2>/dev/null; or echo dev) end # --- Build --- if __should_run build set -l ldflags "-s -w -X git.secluded.site/crush/internal/version.Version=$tag" rm -rf dist mkdir -p dist for target in $targets set -l os (echo $target | cut -d/ -f1) set -l arch (echo $target | cut -d/ -f2) set -l ext "" if test "$os" = windows set ext .exe end echo "Building $os/$arch..." env CGO_ENABLED=0 GOEXPERIMENT=greenteagc GOOS=$os GOARCH=$arch \ go build -o "dist/crush-$tag-$os-$arch$ext" -ldflags "$ldflags"; or begin echo "Error: build failed for $os/$arch" >&2 exit 1 end end end # --- Pack --- if __should_run pack for suffix in $pack_targets set -l bin "dist/crush-$tag-$suffix" if test -f "$bin" echo "Packing $suffix..." upx -q "$bin" end end end # --- Upload --- if __should_run upload fish -c "release upload crush $tag --latest dist/*" end