mirror of
https://github.com/oneclickvirt/ecs.git
synced 2025-12-24 12:37:53 +08:00
480 lines
18 KiB
YAML
480 lines
18 KiB
YAML
name: Build and Release
|
||
on:
|
||
workflow_dispatch:
|
||
tags:
|
||
- "v*.*.*"
|
||
|
||
jobs:
|
||
build:
|
||
name: Release Check And Build
|
||
runs-on: ubuntu-latest
|
||
steps:
|
||
- name: Checkout code
|
||
uses: actions/checkout@v4
|
||
with:
|
||
fetch-depth: 0
|
||
|
||
- name: Get latest tag
|
||
id: tag
|
||
run: |
|
||
TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "v0.1.0")
|
||
echo "tag=$TAG" >> $GITHUB_OUTPUT
|
||
echo "version=${TAG#v}" >> $GITHUB_OUTPUT
|
||
|
||
- name: Generate changelog
|
||
id: changelog
|
||
run: |
|
||
TAG="${{ steps.tag.outputs.tag }}"
|
||
PREV_TAG=$(git describe --tags --abbrev=0 "$TAG^" 2>/dev/null || echo "")
|
||
if [ -z "$PREV_TAG" ]; then
|
||
CHANGELOG=$(git log --oneline --pretty=format:"* %H %s" "$TAG" | head -20)
|
||
else
|
||
CHANGELOG=$(git log --oneline --pretty=format:"* %H %s" "$PREV_TAG..$TAG")
|
||
fi
|
||
FULL_CHANGELOG="## Changelog"$'\n'"$CHANGELOG"
|
||
echo "$FULL_CHANGELOG" > changelog.txt
|
||
echo "changelog<<EOF" >> $GITHUB_OUTPUT
|
||
echo "$FULL_CHANGELOG" >> $GITHUB_OUTPUT
|
||
echo "EOF" >> $GITHUB_OUTPUT
|
||
|
||
- name: Create release if not exists
|
||
run: |
|
||
TAG="${{ steps.tag.outputs.tag }}"
|
||
RELEASE_EXISTS=$(curl -s -H "Authorization: Bearer ${{ secrets.GHT }}" "https://api.github.com/repos/${{ github.repository }}/releases/tags/$TAG" | jq -r '.id // empty')
|
||
if [ -z "$RELEASE_EXISTS" ]; then
|
||
echo "Creating release for tag $TAG"
|
||
CHANGELOG_BODY=$(cat changelog.txt | jq -Rs .)
|
||
RELEASE_RESPONSE=$(curl -s -X POST -H "Authorization: Bearer ${{ secrets.GHT }}" \
|
||
-H "Content-Type: application/json" \
|
||
-d "{\"tag_name\":\"$TAG\",\"name\":\"$TAG\",\"body\":$CHANGELOG_BODY,\"draft\":false,\"prerelease\":false}" \
|
||
"https://api.github.com/repos/${{ github.repository }}/releases")
|
||
echo "Release created: $(echo $RELEASE_RESPONSE | jq -r '.id')"
|
||
else
|
||
echo "Release already exists for tag $TAG"
|
||
fi
|
||
|
||
- name: Delete existing release assets
|
||
run: |
|
||
TAG="${{ steps.tag.outputs.tag }}"
|
||
RELEASE_ID=$(curl -s -H "Authorization: Bearer ${{ secrets.GHT }}" "https://api.github.com/repos/${{ github.repository }}/releases/tags/$TAG" | jq -r '.id')
|
||
if [ "$RELEASE_ID" != "null" ]; then
|
||
echo "Deleting existing release assets..."
|
||
ASSETS=$(curl -s -H "Accept: application/vnd.github.v3+json" "https://api.github.com/repos/${{ github.repository }}/releases/$RELEASE_ID/assets" | jq -r '.[] | .id')
|
||
for asset in $ASSETS; do
|
||
echo "Deleting asset with ID: $asset"
|
||
curl -s -X DELETE -H "Authorization: Bearer ${{ secrets.GHT }}" "https://api.github.com/repos/${{ github.repository }}/releases/assets/$asset"
|
||
done
|
||
sleep 30
|
||
fi
|
||
|
||
release-binary:
|
||
name: Release Go Binary
|
||
needs: build
|
||
strategy:
|
||
fail-fast: false
|
||
matrix:
|
||
include:
|
||
- goos: linux
|
||
goarch: amd64
|
||
cgo_enabled: "1"
|
||
cc: x86_64-linux-gnu-gcc
|
||
cflags: "-O2 -static -fno-stack-protector"
|
||
ldflags: "-extldflags=-static -s -w"
|
||
packages: "build-essential gcc"
|
||
runner: ubuntu-latest
|
||
|
||
- goos: linux
|
||
goarch: 386
|
||
cgo_enabled: "1"
|
||
cc: x86_64-linux-gnu-gcc
|
||
cflags: "-m32 -O1 -march=i686 -mtune=generic -fno-stack-protector"
|
||
ldflags: "-extldflags=-static -s -w"
|
||
packages: "build-essential gcc-multilib"
|
||
runner: ubuntu-latest
|
||
|
||
- goos: linux
|
||
goarch: arm64
|
||
cgo_enabled: "1"
|
||
cc: aarch64-linux-gnu-gcc
|
||
cflags: "-O1 -fno-stack-protector"
|
||
ldflags: "-extldflags=-static -s -w"
|
||
packages: "build-essential gcc-aarch64-linux-gnu"
|
||
runner: ubuntu-latest
|
||
|
||
- goos: linux
|
||
goarch: riscv64
|
||
cgo_enabled: "1"
|
||
cc: riscv64-linux-gnu-gcc
|
||
cflags: "-O1 -fno-stack-protector"
|
||
ldflags: "-extldflags=-static -s -w"
|
||
packages: "build-essential gcc-riscv64-linux-gnu"
|
||
runner: ubuntu-latest
|
||
|
||
- goos: linux
|
||
goarch: mips64
|
||
cgo_enabled: "1"
|
||
cc: mips64-linux-gnuabi64-gcc
|
||
cflags: "-O1 -fno-stack-protector"
|
||
ldflags: "-extldflags=-static -s -w"
|
||
packages: "build-essential gcc-mips64-linux-gnuabi64"
|
||
runner: ubuntu-latest
|
||
|
||
- goos: linux
|
||
goarch: mips64le
|
||
cgo_enabled: "1"
|
||
cc: mips64el-linux-gnuabi64-gcc
|
||
cflags: "-O1 -fno-stack-protector"
|
||
ldflags: "-extldflags=-static -s -w"
|
||
packages: "build-essential gcc-mips64el-linux-gnuabi64"
|
||
runner: ubuntu-latest
|
||
|
||
- goos: linux
|
||
goarch: ppc64le
|
||
cgo_enabled: "1"
|
||
cc: powerpc64le-linux-gnu-gcc
|
||
cflags: "-O1 -fno-stack-protector"
|
||
ldflags: "-extldflags=-static -s -w"
|
||
packages: "build-essential gcc-powerpc64le-linux-gnu"
|
||
runner: ubuntu-latest
|
||
|
||
- goos: windows
|
||
goarch: amd64
|
||
cgo_enabled: "1"
|
||
cc: x86_64-w64-mingw32-gcc
|
||
cflags: "-O2 -static-libgcc -static-libstdc++"
|
||
ldflags: "-extldflags=-static -s -w"
|
||
packages: "build-essential gcc-mingw-w64-x86-64"
|
||
runner: ubuntu-latest
|
||
|
||
- goos: windows
|
||
goarch: 386
|
||
cgo_enabled: "1"
|
||
cc: i686-w64-mingw32-gcc
|
||
cflags: "-O2 -static-libgcc -static-libstdc++"
|
||
ldflags: "-extldflags=-static -s -w"
|
||
packages: "build-essential gcc-mingw-w64-i686"
|
||
runner: ubuntu-latest
|
||
|
||
- goos: darwin
|
||
goarch: amd64
|
||
cgo_enabled: "1"
|
||
cc: "clang --target=x86_64-apple-darwin"
|
||
cflags: "-O2 -arch x86_64 -mmacosx-version-min=10.12"
|
||
ldflags: "-s -w"
|
||
runner: ubuntu-latest
|
||
requires_osxcross: true
|
||
|
||
- goos: darwin
|
||
goarch: arm64
|
||
cgo_enabled: "1"
|
||
cc: "clang --target=aarch64-apple-darwin"
|
||
cflags: "-O2 -arch arm64 -mmacosx-version-min=11.0"
|
||
ldflags: "-s -w"
|
||
runner: ubuntu-latest
|
||
requires_osxcross: true
|
||
|
||
- goos: linux
|
||
goarch: arm
|
||
cgo_enabled: "0"
|
||
ldflags: "-s -w"
|
||
runner: ubuntu-latest
|
||
|
||
- goos: linux
|
||
goarch: s390x
|
||
cgo_enabled: "0"
|
||
ldflags: "-s -w"
|
||
runner: ubuntu-latest
|
||
|
||
- goos: linux
|
||
goarch: mips
|
||
cgo_enabled: "0"
|
||
ldflags: "-s -w"
|
||
runner: ubuntu-latest
|
||
|
||
- goos: linux
|
||
goarch: mipsle
|
||
cgo_enabled: "0"
|
||
ldflags: "-s -w"
|
||
runner: ubuntu-latest
|
||
|
||
- goos: linux
|
||
goarch: ppc64
|
||
cgo_enabled: "0"
|
||
ldflags: "-s -w"
|
||
runner: ubuntu-latest
|
||
|
||
- goos: windows
|
||
goarch: arm64
|
||
cgo_enabled: "0"
|
||
ldflags: "-s -w"
|
||
runner: ubuntu-latest
|
||
|
||
- goos: freebsd
|
||
goarch: amd64
|
||
cgo_enabled: "0"
|
||
ldflags: "-s -w"
|
||
runner: ubuntu-latest
|
||
|
||
- goos: freebsd
|
||
goarch: arm64
|
||
cgo_enabled: "0"
|
||
ldflags: "-s -w"
|
||
runner: ubuntu-latest
|
||
|
||
runs-on: ${{ matrix.runner }}
|
||
steps:
|
||
- name: Checkout code
|
||
uses: actions/checkout@v4
|
||
with:
|
||
fetch-depth: 0
|
||
|
||
- name: Set up Go
|
||
uses: actions/setup-go@v5
|
||
with:
|
||
go-version: 1.23.4
|
||
|
||
- name: Configure Git for Private Modules
|
||
run: |
|
||
git config --global url."https://${{ secrets.GHT }}@github.com/".insteadOf "https://github.com/"
|
||
git config --global url."git@github.com:".insteadOf "https://github.com/"
|
||
env:
|
||
GITHUB_TOKEN: ${{ secrets.GHT }}
|
||
|
||
# 只在非macOS环境安装交叉编译工具
|
||
- name: Install cross-compilation tools
|
||
if: matrix.runner != 'macos-latest'
|
||
run: |
|
||
sudo apt-get update || true
|
||
case "${{ matrix.goos }}-${{ matrix.goarch }}" in
|
||
linux-386)
|
||
sudo apt-get install -y build-essential gcc-multilib g++-multilib ;;
|
||
linux-arm64)
|
||
sudo apt-get install -y build-essential gcc-aarch64-linux-gnu ;;
|
||
linux-riscv64)
|
||
sudo apt-get install -y build-essential gcc-riscv64-linux-gnu ;;
|
||
linux-mips64)
|
||
sudo apt-get install -y build-essential gcc-mips64-linux-gnuabi64 ;;
|
||
linux-mips64le)
|
||
sudo apt-get install -y build-essential gcc-mips64el-linux-gnuabi64 ;;
|
||
linux-ppc64le)
|
||
sudo apt-get install -y build-essential gcc-powerpc64le-linux-gnu ;;
|
||
windows-amd64|windows-386)
|
||
sudo apt-get install -y build-essential gcc-mingw-w64-x86-64 gcc-mingw-w64-i686 ;;
|
||
*)
|
||
sudo apt-get install -y build-essential || true ;;
|
||
esac
|
||
|
||
# 需要支持CGO的Darwin交叉编译,需要安装osxcross
|
||
- name: Install osxcross for Darwin
|
||
if: matrix.requires_osxcross == true
|
||
run: |
|
||
git clone https://github.com/tpoechtrager/osxcross.git
|
||
cd osxcross
|
||
wget -nc https://github.com/joseluisq/macosx-sdks/releases/download/12.3/MacOSX12.3.sdk.tar.xz
|
||
mv MacOSX12.3.sdk.tar.xz tarballs/
|
||
UNATTENDED=yes OSX_VERSION_MIN=10.12 ./build.sh
|
||
echo "$PWD/target/bin" >> $GITHUB_PATH
|
||
echo "OSXCROSS_ROOT=$PWD" >> $GITHUB_ENV
|
||
|
||
- name: Get latest tag
|
||
id: tag
|
||
run: |
|
||
TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "v0.1.0")
|
||
echo "tag=$TAG" >> $GITHUB_OUTPUT
|
||
echo "version=${TAG#v}" >> $GITHUB_OUTPUT
|
||
|
||
- name: Build Binary
|
||
run: |
|
||
go clean -modcache
|
||
export CGO_ENABLED=${{ matrix.cgo_enabled }}
|
||
export GOOS=${{ matrix.goos }}
|
||
export GOARCH=${{ matrix.goarch }}
|
||
if [[ -n "${{ matrix.goarm }}" ]]; then
|
||
export GOARM=${{ matrix.goarm }}
|
||
fi
|
||
if [[ -n "${{ matrix.gomips }}" ]]; then
|
||
export GOMIPS=${{ matrix.gomips }}
|
||
fi
|
||
if [[ "${{ matrix.cgo_enabled }}" == "1" && "${{ matrix.goos }}" == "darwin" ]]; then
|
||
if [[ "${{ matrix.goarch }}" == "amd64" ]]; then
|
||
export CC="x86_64-apple-darwin21.4-clang"
|
||
export CXX="x86_64-apple-darwin21.4-clang++"
|
||
elif [[ "${{ matrix.goarch }}" == "arm64" ]]; then
|
||
export CC="aarch64-apple-darwin21.4-clang"
|
||
export CXX="aarch64-apple-darwin21.4-clang++"
|
||
fi
|
||
export CGO_CFLAGS="${{ matrix.cflags }}"
|
||
export CGO_LDFLAGS="${{ matrix.ldflags }}"
|
||
export OSXCROSS_ROOT="${OSXCROSS_ROOT}"
|
||
elif [[ "${{ matrix.cgo_enabled }}" == "1" && "${{ matrix.runner }}" != "macos-latest" ]]; then
|
||
export CC="${{ matrix.cc }}"
|
||
export CGO_CFLAGS="${{ matrix.cflags }}"
|
||
if [[ "${{ matrix.goos }}" == "windows" ]]; then
|
||
export CGO_LDFLAGS="-static-libgcc -static-libstdc++"
|
||
fi
|
||
fi
|
||
echo "CGO Configuration:"
|
||
echo "CGO_ENABLED=$CGO_ENABLED"
|
||
echo "GOOS=$GOOS"
|
||
echo "GOARCH=$GOARCH"
|
||
echo "CC=$CC"
|
||
echo "CGO_CFLAGS=$CGO_CFLAGS"
|
||
echo "CGO_LDFLAGS=$CGO_LDFLAGS"
|
||
if [[ "${{ matrix.cgo_enabled }}" == "1" ]]; then
|
||
echo "Testing compiler..."
|
||
echo 'int main() { return 0; }' > test.c
|
||
$CC $CGO_CFLAGS test.c -o test || (echo "Compiler test failed" && exit 1)
|
||
rm -f test.c test
|
||
echo "Compiler test passed"
|
||
fi
|
||
go mod download
|
||
go mod tidy -v
|
||
mkdir -p bin
|
||
BINARY_NAME="goecs"
|
||
if [[ "${{ matrix.goos }}" == "windows" ]]; then
|
||
BINARY_NAME="${BINARY_NAME}.exe"
|
||
fi
|
||
LDFLAGS="-s -w -X main.version=${{ steps.tag.outputs.version }} -X main.arch=${{ matrix.goarch }}"
|
||
if [[ "${{ matrix.cgo_enabled }}" == "1" ]]; then
|
||
LDFLAGS="${LDFLAGS} -checklinkname=0 ${{ matrix.ldflags }}"
|
||
echo "Building $BINARY_NAME for ${{ matrix.goos }}/${{ matrix.goarch }} with CGO"
|
||
echo "Final build command: CGO_ENABLED=$CGO_ENABLED GOOS=$GOOS GOARCH=$GOARCH CC=$CC go build"
|
||
env CGO_ENABLED=$CGO_ENABLED GOOS=$GOOS GOARCH=$GOARCH CC="$CC" CGO_CFLAGS="$CGO_CFLAGS" CGO_LDFLAGS="$CGO_LDFLAGS" \
|
||
go build -o bin/$BINARY_NAME -v -ldflags="$LDFLAGS" -trimpath ./
|
||
else
|
||
LDFLAGS="${LDFLAGS} -checklinkname=0 ${{ matrix.ldflags }}"
|
||
echo "Building $BINARY_NAME for ${{ matrix.goos }}/${{ matrix.goarch }} without CGO"
|
||
env CGO_ENABLED=0 GOOS=$GOOS GOARCH=$GOARCH \
|
||
go build -o bin/$BINARY_NAME -v -ldflags="$LDFLAGS" -trimpath ./
|
||
fi
|
||
if [[ -f "bin/$BINARY_NAME" ]]; then
|
||
echo "Successfully built bin/$BINARY_NAME"
|
||
ls -la bin/$BINARY_NAME
|
||
else
|
||
echo "Build failed for ${{ matrix.goos }}/${{ matrix.goarch }}"
|
||
exit 1
|
||
fi
|
||
|
||
- name: Create ZIP archive
|
||
run: |
|
||
cd bin
|
||
BINARY_NAME="goecs"
|
||
if [[ "${{ matrix.goos }}" == "windows" ]]; then
|
||
BINARY_NAME="${BINARY_NAME}.exe"
|
||
fi
|
||
ZIP_NAME="goecs_${{ matrix.goos }}_${{ matrix.goarch }}"
|
||
if [[ -n "${{ matrix.goarm }}" ]]; then
|
||
ZIP_NAME="${ZIP_NAME}v${{ matrix.goarm }}"
|
||
fi
|
||
if [[ -n "${{ matrix.gomips }}" ]]; then
|
||
ZIP_NAME="${ZIP_NAME}_${{ matrix.gomips }}"
|
||
fi
|
||
ZIP_NAME="${ZIP_NAME}.zip"
|
||
zip "$ZIP_NAME" "$BINARY_NAME"
|
||
echo "Created $ZIP_NAME"
|
||
ls -la "$ZIP_NAME"
|
||
|
||
- name: Upload to Release
|
||
run: |
|
||
TAG="${{ steps.tag.outputs.tag }}"
|
||
RELEASE_ID=$(curl -s -H "Authorization: Bearer ${{ secrets.GHT }}" "https://api.github.com/repos/${{ github.repository }}/releases/tags/$TAG" | jq -r '.id')
|
||
cd bin
|
||
for file in *.zip; do
|
||
if [[ -f "$file" ]]; then
|
||
echo "Uploading $file to release..."
|
||
curl -s -H "Authorization: Bearer ${{ secrets.GHT }}" \
|
||
-H "Content-Type: application/zip" \
|
||
--data-binary @"$file" \
|
||
"https://uploads.github.com/repos/${{ github.repository }}/releases/$RELEASE_ID/assets?name=$file"
|
||
fi
|
||
done
|
||
|
||
checksums:
|
||
name: Generate Checksums
|
||
runs-on: ubuntu-latest
|
||
needs: release-binary
|
||
steps:
|
||
- name: Checkout code
|
||
uses: actions/checkout@v4
|
||
with:
|
||
fetch-depth: 0
|
||
|
||
- name: Get latest tag
|
||
id: tag
|
||
run: |
|
||
TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "v0.1.0")
|
||
echo "tag=$TAG" >> $GITHUB_OUTPUT
|
||
|
||
- name: Download release assets
|
||
run: |
|
||
TAG="${{ steps.tag.outputs.tag }}"
|
||
RELEASE_ID=$(curl -s -H "Authorization: Bearer ${{ secrets.GHT }}" "https://api.github.com/repos/${{ github.repository }}/releases/tags/$TAG" | jq -r '.id')
|
||
mkdir -p assets
|
||
ASSETS=$(curl -s -H "Accept: application/vnd.github.v3+json" "https://api.github.com/repos/${{ github.repository }}/releases/$RELEASE_ID/assets")
|
||
echo "$ASSETS" | jq -r '.[] | select(.name | endswith(".zip")) | .browser_download_url' | while read url; do
|
||
filename=$(basename "$url")
|
||
echo "Downloading $filename..."
|
||
curl -L -H "Authorization: Bearer ${{ secrets.GHT }}" "$url" -o "assets/$filename"
|
||
done
|
||
|
||
- name: Generate checksums
|
||
run: |
|
||
cd assets
|
||
sha256sum *.zip > checksums.txt
|
||
if [[ -f "../goecs.sh" ]]; then
|
||
sha256sum ../goecs.sh >> checksums.txt
|
||
fi
|
||
cat checksums.txt
|
||
|
||
- name: Upload checksums
|
||
run: |
|
||
TAG="${{ steps.tag.outputs.tag }}"
|
||
RELEASE_ID=$(curl -s -H "Authorization: Bearer ${{ secrets.GHT }}" "https://api.github.com/repos/${{ github.repository }}/releases/tags/$TAG" | jq -r '.id')
|
||
|
||
curl -s -H "Authorization: Bearer ${{ secrets.GHT }}" \
|
||
-H "Content-Type: text/plain" \
|
||
--data-binary @assets/checksums.txt \
|
||
"https://uploads.github.com/repos/${{ github.repository }}/releases/$RELEASE_ID/assets?name=checksums.txt"
|
||
|
||
update-script:
|
||
name: Update Script Version
|
||
runs-on: ubuntu-latest
|
||
needs: checksums
|
||
steps:
|
||
- name: Checkout code
|
||
uses: actions/checkout@v4
|
||
with:
|
||
fetch-depth: 0
|
||
|
||
- name: Get latest tag
|
||
id: tag
|
||
run: |
|
||
TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "v0.1.0")
|
||
echo "tag=$TAG" >> $GITHUB_OUTPUT
|
||
echo "version=${TAG#v}" >> $GITHUB_OUTPUT
|
||
|
||
- name: Update goecs.sh version
|
||
run: |
|
||
VERSION="${{ steps.tag.outputs.version }}"
|
||
BRANCH="master"
|
||
git config --global user.name "github-actions[bot]"
|
||
git config --global user.email "github-actions[bot]@users.noreply.github.com"
|
||
git config --global --unset url."git@github.com:".insteadOf || true
|
||
git fetch origin $BRANCH
|
||
git checkout $BRANCH
|
||
if [ -f "goecs.sh" ]; then
|
||
sed -i "s/\(_yellow \"Unable to get version info, using default version \).*\(\".*\)/\1$VERSION\2/" "goecs.sh"
|
||
sed -i "s/\(ECS_VERSION=\"\).*\(\"\)/\1$VERSION\2/" "goecs.sh"
|
||
if ! git diff --quiet "goecs.sh"; then
|
||
git add "goecs.sh"
|
||
git commit -m "chore: update ECS_VERSION to $VERSION in goecs.sh"
|
||
git push origin $BRANCH
|
||
echo "Updated goecs.sh with version $VERSION"
|
||
else
|
||
echo "No changes needed in goecs.sh"
|
||
fi
|
||
else
|
||
echo "goecs.sh not found, skipping version update"
|
||
fi
|
||
env:
|
||
GITHUB_TOKEN: ${{ secrets.GHT }} |