You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
337 lines
9.7 KiB
337 lines
9.7 KiB
name: Release
|
|
|
|
permissions:
|
|
contents: read
|
|
|
|
on:
|
|
push:
|
|
branches:
|
|
- main
|
|
workflow_dispatch:
|
|
|
|
jobs:
|
|
build:
|
|
name: Build binaries
|
|
runs-on: ubuntu-latest
|
|
strategy:
|
|
matrix:
|
|
include:
|
|
- goos: linux
|
|
goarch: amd64
|
|
cgo: 0
|
|
- goos: linux
|
|
goarch: arm64
|
|
cgo: 0
|
|
- goos: linux
|
|
goarch: 386
|
|
cgo: 0
|
|
- goos: linux
|
|
goarch: arm
|
|
goarm: "7"
|
|
cgo: 0
|
|
- goos: linux
|
|
goarch: mipsle
|
|
gomips: softfloat
|
|
cgo: 0
|
|
- goos: linux
|
|
goarch: mips
|
|
gomips: softfloat
|
|
cgo: 0
|
|
- goos: linux
|
|
goarch: mips64le
|
|
gomips: softfloat
|
|
cgo: 0
|
|
- goos: linux
|
|
goarch: riscv64
|
|
cgo: 0
|
|
- goos: darwin
|
|
goarch: amd64
|
|
cgo: 0
|
|
- goos: darwin
|
|
goarch: arm64
|
|
cgo: 0
|
|
- goos: windows
|
|
goarch: amd64
|
|
cgo: 0
|
|
- goos: windows
|
|
goarch: arm64
|
|
cgo: 0
|
|
- goos: windows
|
|
goarch: 386
|
|
cgo: 0
|
|
- goos: android
|
|
goarch: arm64
|
|
cgo: 1
|
|
api: 21
|
|
- goos: android
|
|
goarch: arm
|
|
cgo: 1
|
|
api: 21
|
|
- goos: freebsd
|
|
goarch: amd64
|
|
cgo: 0
|
|
|
|
steps:
|
|
- name: Check out code
|
|
uses: actions/checkout@v6
|
|
|
|
- name: Set up Go
|
|
uses: actions/setup-go@v6
|
|
with:
|
|
go-version: "1.25.5"
|
|
|
|
# Install Android NDK only for android rows
|
|
- name: Setup Android NDK
|
|
if: matrix.goos == 'android'
|
|
id: setup-ndk
|
|
uses: nttld/setup-ndk@v1
|
|
with:
|
|
ndk-version: r26d
|
|
add-to-path: false
|
|
|
|
- name: Build
|
|
env:
|
|
GOOS: ${{ matrix.goos }}
|
|
GOARCH: ${{ matrix.goarch }}
|
|
GOMIPS: ${{ matrix.gomips }}
|
|
GOARM: ${{ matrix.goarm }}
|
|
CGO_ENABLED: ${{ matrix.cgo }}
|
|
ANDROID_API: ${{ matrix.api }}
|
|
ANDROID_NDK_HOME: ${{ steps.setup-ndk.outputs.ndk-path }}
|
|
VERSION: ${{ github.ref_name }}
|
|
run: |
|
|
echo "Building for $GOOS/$GOARCH${GOARM:+/arm$GOARM} (CGO_ENABLED=$CGO_ENABLED)"
|
|
|
|
if [ "$GOOS" = "android" ]; then
|
|
if [ -z "$ANDROID_NDK_HOME" ]; then
|
|
echo "ANDROID_NDK_HOME is not set – did setup-ndk run?"
|
|
exit 1
|
|
fi
|
|
|
|
TOOLCHAIN_BIN="$ANDROID_NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin"
|
|
|
|
if [ "$GOARCH" = "arm64" ]; then
|
|
export CC="$TOOLCHAIN_BIN/aarch64-linux-android${ANDROID_API}-clang"
|
|
elif [ "$GOARCH" = "arm" ]; then
|
|
export CC="$TOOLCHAIN_BIN/armv7a-linux-androideabi${ANDROID_API}-clang"
|
|
else
|
|
echo "Unsupported ANDROID GOARCH=$GOARCH"
|
|
exit 1
|
|
fi
|
|
|
|
echo "Using Android NDK CC=$CC"
|
|
fi
|
|
|
|
mkdir -p dist
|
|
|
|
# Set extension for windows
|
|
if [ "${GOOS}" = "windows" ]; then
|
|
EXT=.exe
|
|
else
|
|
EXT=
|
|
fi
|
|
|
|
GOOS=$GOOS GOARCH=$GOARCH GOARM=$GOARM GOMIPS=$GOMIPS \
|
|
go build -ldflags "-s -w -checklinkname=0" -trimpath \
|
|
-o "dist/client-${GOOS}-${GOARCH}${EXT}" \
|
|
./client
|
|
|
|
GOOS=$GOOS GOARCH=$GOARCH GOARM=$GOARM GOMIPS=$GOMIPS \
|
|
go build -ldflags "-s -w -checklinkname=0" -trimpath \
|
|
-o "dist/server-${GOOS}-${GOARCH}${EXT}" \
|
|
./server
|
|
|
|
- name: Upload artifact
|
|
uses: actions/upload-artifact@v6
|
|
with:
|
|
name: good-turn-${{ matrix.goos }}-${{ matrix.goarch }}
|
|
path: dist/**
|
|
|
|
release:
|
|
name: Create GitHub Release
|
|
needs: build
|
|
runs-on: ubuntu-latest
|
|
outputs:
|
|
should_release: ${{ steps.meta.outputs.should_release }}
|
|
tag_name: ${{ steps.meta.outputs.tag_name }}
|
|
permissions:
|
|
contents: write
|
|
steps:
|
|
- name: Check out code
|
|
uses: actions/checkout@v6
|
|
with:
|
|
fetch-depth: 0
|
|
fetch-tags: true
|
|
|
|
- name: Download build artifacts
|
|
uses: actions/download-artifact@v7
|
|
with:
|
|
path: dist
|
|
|
|
- name: Prepare release metadata
|
|
id: meta
|
|
run: |
|
|
LATEST_TAG="$(git tag -l | grep -E '^(v)?[0-9]+\.[0-9]+\.[0-9]+$' | sort -V | tail -n 1 || true)"
|
|
PREFIX=""
|
|
BASE_VERSION="$LATEST_TAG"
|
|
|
|
if [ -z "$LATEST_TAG" ]; then
|
|
BASE_VERSION="0.0.0"
|
|
elif [ "${LATEST_TAG#v}" != "$LATEST_TAG" ]; then
|
|
PREFIX="v"
|
|
BASE_VERSION="${LATEST_TAG#v}"
|
|
fi
|
|
|
|
IFS=. read -r MAJOR MINOR PATCH <<< "$BASE_VERSION"
|
|
|
|
if [ -n "$LATEST_TAG" ]; then
|
|
RANGE="$LATEST_TAG..HEAD"
|
|
else
|
|
RANGE="HEAD"
|
|
fi
|
|
|
|
COMMITS="$(git log --no-merges --format='%s' "$RANGE")"
|
|
BUMP=""
|
|
|
|
if printf '%s\n' "$COMMITS" | grep -Eiq '^break([(:! ]|$)'; then
|
|
BUMP="major"
|
|
MAJOR=$((MAJOR + 1))
|
|
MINOR=0
|
|
PATCH=0
|
|
elif printf '%s\n' "$COMMITS" | grep -Eiq '^feat([(:! ]|$)'; then
|
|
BUMP="minor"
|
|
MINOR=$((MINOR + 1))
|
|
PATCH=0
|
|
elif printf '%s\n' "$COMMITS" | grep -Eiq '^fix([(:! ]|$)'; then
|
|
BUMP="patch"
|
|
PATCH=$((PATCH + 1))
|
|
fi
|
|
|
|
NEXT_VERSION="${MAJOR}.${MINOR}.${PATCH}"
|
|
NEXT_TAG="${PREFIX}${NEXT_VERSION}"
|
|
|
|
{
|
|
echo "previous_tag=$LATEST_TAG"
|
|
echo "range=$RANGE"
|
|
echo "bump=$BUMP"
|
|
echo "should_release=$([ -n "$BUMP" ] && echo true || echo false)"
|
|
echo "tag_name=$NEXT_TAG"
|
|
echo "release_name=$NEXT_TAG"
|
|
echo "body_path=release-notes.md"
|
|
} >> "$GITHUB_OUTPUT"
|
|
|
|
- name: Generate release notes from commit messages
|
|
id: notes
|
|
if: steps.meta.outputs.should_release == 'true'
|
|
env:
|
|
PREVIOUS_TAG: ${{ steps.meta.outputs.previous_tag }}
|
|
NEXT_TAG: ${{ steps.meta.outputs.tag_name }}
|
|
BUMP: ${{ steps.meta.outputs.bump }}
|
|
RANGE: ${{ steps.meta.outputs.range }}
|
|
run: |
|
|
strip_prefix() {
|
|
sed -E 's/^(feat|fix|break)([(!:]|[[:space:]])+[[:space:]]*//I'
|
|
}
|
|
|
|
FEATURES="$(git log --no-merges --format='%s (%h)' "$RANGE" | grep -Ei '^feat([(:! ]|$)' | strip_prefix | LC_ALL=C sort -f || true)"
|
|
FIXES="$(git log --no-merges --format='%s (%h)' "$RANGE" | grep -Ei '^fix([(:! ]|$)' | strip_prefix | LC_ALL=C sort -f || true)"
|
|
BREAKING="$(git log --no-merges --format='%s (%h)' "$RANGE" | grep -Ei '^break([(:! ]|$)' | strip_prefix | LC_ALL=C sort -f || true)"
|
|
|
|
{
|
|
echo "body_path=release-notes.md"
|
|
} >> "$GITHUB_OUTPUT"
|
|
|
|
{
|
|
if [ -n "$BREAKING" ]; then
|
|
echo "### Breaking Changes"
|
|
echo
|
|
printf '%s\n' "$BREAKING" | sed 's/^/- /'
|
|
echo
|
|
fi
|
|
|
|
if [ -n "$FEATURES" ]; then
|
|
echo "### Features"
|
|
echo
|
|
printf '%s\n' "$FEATURES" | sed 's/^/- /'
|
|
echo
|
|
fi
|
|
|
|
if [ -n "$FIXES" ]; then
|
|
echo "### Bug Fixes"
|
|
echo
|
|
printf '%s\n' "$FIXES" | sed 's/^/- /'
|
|
echo
|
|
fi
|
|
} > release-notes.md
|
|
|
|
- name: Create Release
|
|
if: steps.meta.outputs.should_release == 'true'
|
|
uses: softprops/action-gh-release@v2
|
|
with:
|
|
# upload every file in dist/ including nested files
|
|
files: |
|
|
dist/**
|
|
tag_name: ${{ steps.meta.outputs.tag_name }}
|
|
target_commitish: ${{ github.sha }}
|
|
name: ${{ steps.meta.outputs.release_name }}
|
|
body_path: ${{ steps.meta.outputs.body_path }}
|
|
overwrite_files: true
|
|
env:
|
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
|
|
- name: Skip release when no semantic commit is found
|
|
if: steps.meta.outputs.should_release != 'true'
|
|
run: |
|
|
echo "No new semantic release created."
|
|
echo "Add a commit starting with break, feat, or fix after the latest tag."
|
|
|
|
docker:
|
|
name: Publish Docker image
|
|
needs: release
|
|
if: needs.release.outputs.should_release == 'true'
|
|
runs-on: ubuntu-latest
|
|
permissions:
|
|
contents: read
|
|
packages: write
|
|
steps:
|
|
- name: Check out code
|
|
uses: actions/checkout@v6
|
|
|
|
- name: Set up QEMU
|
|
uses: docker/setup-qemu-action@v4
|
|
|
|
- name: Set up Docker Buildx
|
|
uses: docker/setup-buildx-action@v4
|
|
|
|
- name: Prepare image name
|
|
id: image
|
|
env:
|
|
REPOSITORY: ${{ github.repository }}
|
|
run: |
|
|
echo "name=ghcr.io/$(echo "$REPOSITORY" | tr '[:upper:]' '[:lower:]')" >> "$GITHUB_OUTPUT"
|
|
|
|
- name: Log in to GitHub Container Registry
|
|
uses: docker/login-action@v4
|
|
with:
|
|
registry: ghcr.io
|
|
username: ${{ github.actor }}
|
|
password: ${{ secrets.GITHUB_TOKEN }}
|
|
|
|
- name: Extract Docker metadata
|
|
id: meta
|
|
uses: docker/metadata-action@v6
|
|
with:
|
|
images: ${{ steps.image.outputs.name }}
|
|
tags: |
|
|
type=raw,value=latest
|
|
type=raw,value=${{ needs.release.outputs.tag_name }}
|
|
|
|
- name: Build and push Docker image
|
|
uses: docker/build-push-action@v7
|
|
with:
|
|
context: .
|
|
file: ./Dockerfile
|
|
platforms: linux/amd64,linux/arm64
|
|
push: true
|
|
tags: ${{ steps.meta.outputs.tags }}
|
|
labels: ${{ steps.meta.outputs.labels }}
|
|
|