feat: add production builds with -s -w stripping and UPX compression

- Add prod builds (stripped) and prod-upx builds (compressed) for Linux
- Add prod builds (stripped) for macOS (UPX not supported)
- Add docker/production-slim for slim images using prod-upx binaries
- Update build-docker.yml to build slim variants
- Update build-macos.yml to sign and notarize all 4 variants
- Add BUILDOPTIONS constant to show build flags in version output
- Add make release-all target for building both dev and prod locally

Linux artifacts: 6 variants (dev, prod, prod-upx for amd64/arm64)
macOS artifacts: 4 variants (dev, prod for amd64/arm64)
Docker images: 6 variants (dev, prod, prod-slim for amd64/arm64)

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Max 2026-02-03 12:27:37 +08:00
parent 6e97de948b
commit 76159373e5
6 changed files with 135 additions and 82 deletions

View file

@ -1,70 +0,0 @@
name: Push docker images to internal registry
on:
# push:
# branches: [main]
# paths:
# - ".github/workflows/docker.yml"
workflow_run:
workflows: ["Build Linux Artifacts"]
types:
- completed
env:
VERSION: 0.10.5
jobs:
build:
if: ${{ github.event.workflow_run.conclusion == 'success' }}
runs-on: ubuntu-latest
timeout-minutes: 120
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Get Version
run: |
echo VERSION=$(cat share/const.go |grep 'const VERSION' | awk '{print $4}' | sed "s/\"//g")-unstable >> $GITHUB_ENV
- name: Check Version
run: echo $VERSION
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to DockerHub
uses: docker/login-action@v3
with:
registry: hub.iqka.com
username: ${{ secrets.DOCKER_INTERNAL_USER }}
password: ${{ secrets.DOCKER_INTERNAL_TOKEN }}
- name: Build Production
timeout-minutes: 60
uses: docker/build-push-action@v6
env:
DOCKER_CONTENT_TRUST: 1
with:
context: ./docker/production
platforms: linux/amd64
build-args: |
VERSION=${{ env.VERSION }}
ARCH=amd64
push: true
tags: hub.iqka.com/yaoapp/yao:${{ env.VERSION }}-amd64
- name: Build Production Arm64
timeout-minutes: 60
uses: docker/build-push-action@v6
env:
DOCKER_CONTENT_TRUST: 1
with:
context: ./docker/production
platforms: linux/arm64
build-args: |
VERSION=${{ env.VERSION }}
ARCH=arm64
push: true
tags: hub.iqka.com/yaoapp/yao:${{ env.VERSION }}-arm64

View file

@ -90,3 +90,29 @@ jobs:
ARCH=arm64
push: true
tags: yaoapp/yao:${{ env.VERSION }}-arm64
- name: Build Production Slim
uses: docker/build-push-action@v6
env:
DOCKER_CONTENT_TRUST: 1
with:
context: ./docker/production-slim
platforms: linux/amd64
build-args: |
VERSION=${{ env.VERSION }}
ARCH=amd64
push: true
tags: yaoapp/yao:${{ env.VERSION }}-amd64-slim
- name: Build Production Slim Arm64
uses: docker/build-push-action@v6
env:
DOCKER_CONTENT_TRUST: 1
with:
context: ./docker/production-slim
platforms: linux/arm64
build-args: |
VERSION=${{ env.VERSION }}
ARCH=arm64
push: true
tags: yaoapp/yao:${{ env.VERSION }}-arm64-slim

View file

@ -114,8 +114,6 @@ jobs:
- name: Make Artifacts MacOS
run: |
make artifacts-macos
mv dist/release/yao-$VERSION-dev-darwin-arm64 dist/release/yao-$VERSION-unstable-darwin-arm64
mv dist/release/yao-$VERSION-dev-darwin-amd64 dist/release/yao-$VERSION-unstable-darwin-amd64
- name: Install Certificates
env:
@ -150,21 +148,31 @@ jobs:
- name: Sign Artifacts
run: |
codesign --deep --force --verbose --timestamp --sign "Developer ID Application: ${{ secrets.APPLE_SIGN }}" dist/release/yao-$VERSION-unstable-darwin-arm64
codesign --deep --force --verbose --timestamp --options runtime --sign "Developer ID Application: ${{ secrets.APPLE_SIGN }}" dist/release/yao-$VERSION-unstable-darwin-amd64
codesign --deep --force --verbose --timestamp --sign "Developer ID Application: ${{ secrets.APPLE_SIGN }}" dist/release/yao-$VERSION-unstable-darwin-amd64
codesign --deep --force --verbose --timestamp --sign "Developer ID Application: ${{ secrets.APPLE_SIGN }}" dist/release/yao-$VERSION-unstable-darwin-arm64-prod
codesign --deep --force --verbose --timestamp --sign "Developer ID Application: ${{ secrets.APPLE_SIGN }}" dist/release/yao-$VERSION-unstable-darwin-amd64-prod
- name: Verify Signature
run: |
codesign --verify --deep --strict --verbose=2 dist/release/yao-$VERSION-unstable-darwin-arm64
codesign --verify --deep --strict --verbose=2 dist/release/yao-$VERSION-unstable-darwin-amd64
codesign --verify --deep --strict --verbose=2 dist/release/yao-$VERSION-unstable-darwin-arm64-prod
codesign --verify --deep --strict --verbose=2 dist/release/yao-$VERSION-unstable-darwin-amd64-prod
- name: Send to Apple Notary Service
run: |
zip -r dist/release/yao-$VERSION-unstable-darwin-arm64.zip dist/release/yao-$VERSION-unstable-darwin-arm64
zip -r dist/release/yao-$VERSION-unstable-darwin-amd64.zip dist/release/yao-$VERSION-unstable-darwin-amd64
zip -r dist/release/yao-$VERSION-unstable-darwin-arm64-prod.zip dist/release/yao-$VERSION-unstable-darwin-arm64-prod
zip -r dist/release/yao-$VERSION-unstable-darwin-amd64-prod.zip dist/release/yao-$VERSION-unstable-darwin-amd64-prod
xcrun notarytool submit dist/release/yao-$VERSION-unstable-darwin-arm64.zip --apple-id "${{ secrets.APPLE_ID }}" --team-id "${{ secrets.APPLE_TEAME_ID }}" --password "${{ secrets.APPLE_APP_SPEC_PASS }}" --output-format json
xcrun notarytool submit dist/release/yao-$VERSION-unstable-darwin-amd64.zip --apple-id "${{ secrets.APPLE_ID }}" --team-id "${{ secrets.APPLE_TEAME_ID }}" --password "${{ secrets.APPLE_APP_SPEC_PASS }}" --output-format json
xcrun notarytool submit dist/release/yao-$VERSION-unstable-darwin-arm64-prod.zip --apple-id "${{ secrets.APPLE_ID }}" --team-id "${{ secrets.APPLE_TEAME_ID }}" --password "${{ secrets.APPLE_APP_SPEC_PASS }}" --output-format json
xcrun notarytool submit dist/release/yao-$VERSION-unstable-darwin-amd64-prod.zip --apple-id "${{ secrets.APPLE_ID }}" --team-id "${{ secrets.APPLE_TEAME_ID }}" --password "${{ secrets.APPLE_APP_SPEC_PASS }}" --output-format json
rm -f dist/release/yao-$VERSION-unstable-darwin-arm64.zip
rm -f dist/release/yao-$VERSION-unstable-darwin-amd64.zip
rm -f dist/release/yao-$VERSION-unstable-darwin-arm64-prod.zip
rm -f dist/release/yao-$VERSION-unstable-darwin-amd64-prod.zip
- name: Archive production artifacts
uses: actions/upload-artifact@v4

View file

@ -467,16 +467,21 @@ artifacts-macos: clean
@CUI_COMMIT=$$(cd ../cui-v1.0 && git log | head -n 1 | awk '{print substr($$2, 0, 12)}') && \
sed -ie "s/const PRCUI = \"DEV\"/const PRCUI = \"$$CUI_COMMIT-${NOW}\"/g" share/const.go
# Making artifacts
# Making artifacts - dev builds (full debug symbols)
mkdir -p dist
CGO_ENABLED=1 GOOS=darwin GOARCH=amd64 go build -v -o dist/yao-${VERSION}-dev-darwin-amd64
CGO_ENABLED=1 GOOS=darwin GOARCH=arm64 go build -v -o dist/yao-${VERSION}-dev-darwin-arm64
CGO_ENABLED=1 GOOS=darwin GOARCH=amd64 go build -v -o dist/yao-${VERSION}-unstable-darwin-amd64
CGO_ENABLED=1 GOOS=darwin GOARCH=arm64 go build -v -o dist/yao-${VERSION}-unstable-darwin-arm64
# Making artifacts - prod builds (stripped, no UPX on macOS)
sed -i.tmp 's/const BUILDOPTIONS = ""/const BUILDOPTIONS = "-s -w (production, stripped)"/g' share/const.go && rm -f share/const.go.tmp
CGO_ENABLED=1 GOOS=darwin GOARCH=amd64 go build -v -ldflags="-s -w" -o dist/yao-${VERSION}-unstable-darwin-amd64-prod
CGO_ENABLED=1 GOOS=darwin GOARCH=arm64 go build -v -ldflags="-s -w" -o dist/yao-${VERSION}-unstable-darwin-arm64-prod
mkdir -p dist/release
mv dist/yao-*-* dist/release/
chmod +x dist/release/yao-*-*
ls -l dist/release/
dist/release/yao-${VERSION}-dev-darwin-amd64 version
dist/release/yao-${VERSION}-unstable-darwin-amd64 version
.PHONY: debug
@ -554,10 +559,10 @@ prepare: clean
@CUI_COMMIT=$$(cd .tmp/cui/v1.0 && git log | head -n 1 | awk '{print substr($$2, 0, 12)}') && \
sed -ie "s/const PRCUI = \"DEV\"/const PRCUI = \"$$CUI_COMMIT-${NOW}\"/g" share/const.go
# make release (development build, ~158M)
# make release (development build only, ~158M)
.PHONY: release
release: prepare
# Making artifacts
# Making artifacts - dev build
mkdir -p dist
CGO_ENABLED=1 go build -v -o dist/release/yao
chmod +x dist/release/yao
@ -574,7 +579,7 @@ release: prepare
codesign --deep --force --verify --verbose --sign "${APPLE_SIGN}" dist/release/yao ; \
fi
# make prod (production build with -s -w, ~111M on macOS, ~45-55M on Linux with UPX)
# make prod (production build only, ~111M on macOS)
.PHONY: prod
prod: prepare
# Set BUILDOPTIONS
@ -584,7 +589,7 @@ prod: prepare
sed -i.tmp 's/const BUILDOPTIONS = ""/const BUILDOPTIONS = "-s -w (production, stripped)"/g' share/const.go && rm -f share/const.go.tmp; \
fi
# Making artifacts
# Making artifacts - prod build
mkdir -p dist
CGO_ENABLED=1 go build -v -ldflags="-s -w" -o dist/release/yao-prod
chmod +x dist/release/yao-prod
@ -620,6 +625,59 @@ prod: prepare
@echo ""
@echo "Test with: dist/release/yao-prod version --all"
# make release-all (build both dev and prod in one go)
.PHONY: release-all
release-all: prepare
# Making artifacts - dev build (~158M)
@echo "Building dev binary..."
mkdir -p dist
CGO_ENABLED=1 go build -v -o dist/release/yao
chmod +x dist/release/yao
# Making artifacts - prod build (~111M on macOS)
@echo "Building prod binary..."
@if [ "$$(uname)" = "Linux" ]; then \
sed -i.tmp 's/const BUILDOPTIONS = ""/const BUILDOPTIONS = "-s -w +upx (production, compressed)"/g' share/const.go && rm -f share/const.go.tmp; \
else \
sed -i.tmp 's/const BUILDOPTIONS = ""/const BUILDOPTIONS = "-s -w (production, stripped)"/g' share/const.go && rm -f share/const.go.tmp; \
fi
CGO_ENABLED=1 go build -v -ldflags="-s -w" -o dist/release/yao-prod
chmod +x dist/release/yao-prod
# UPX compression (Linux only)
@if [ "$$(uname)" = "Linux" ]; then \
echo "Compressing with UPX..."; \
if command -v upx > /dev/null 2>&1; then \
upx --best dist/release/yao-prod; \
else \
echo "WARNING: UPX not found. Install with: apt install upx"; \
echo "Skipping compression."; \
fi; \
else \
echo "Note: UPX compression skipped on macOS (not supported)"; \
fi
# Clean up and restore bindata.go and const.go
cp data/bindata.go.bak data/bindata.go
cp share/const.go.bak share/const.go
rm data/bindata.go.bak
rm share/const.go.bak
rm -rf .tmp
# MacOS Application Signing
@if [ "$(OS)" = "Darwin" ]; then \
codesign --deep --force --verify --verbose --sign "${APPLE_SIGN}" dist/release/yao ; \
codesign --deep --force --verify --verbose --sign "${APPLE_SIGN}" dist/release/yao-prod ; \
fi
@echo ""
@echo "Done! Binaries:"
@ls -lh dist/release/yao dist/release/yao-prod
@echo ""
@echo "Test with:"
@echo " dist/release/yao version --all"
@echo " dist/release/yao-prod version --all"
.PHONY: linux-release
linux-release: clean

View file

@ -0,0 +1,31 @@
# ===========================================
# Yao Production Slim (UPX compressed)
# docker build \
# --build-arg VERSION="${VERSION}" \
# --build-arg ARCH="${ARCH}" \
# -t yaoapp/yao:${VERSION}-${ARCH}-slim .
#
# Build:
# docker build --platform linux/amd64 --build-arg VERSION=1.0.0 --build-arg ARCH=amd64 -t yaoapp/yao:1.0.0-amd64-slim .
# docker build --platform linux/arm64 --build-arg VERSION=1.0.0 --build-arg ARCH=arm64 -t yaoapp/yao:1.0.0-arm64-slim .
#
# Tests:
# docker run --rm yaoapp/yao:1.0.0-amd64-slim yao version
# docker run -d -p 5099:5099 yaoapp/yao:1.0.0-amd64-slim
#
# ===========================================
FROM alpine:latest
ARG VERSION
ARG ARCH
RUN apk --no-cache add curl
RUN curl -fsSL "https://pub-80136338e60643edbb55c6ca8a689cf8.r2.dev/archives/yao-${VERSION}-linux-${ARCH}-prod-upx" > /usr/local/bin/yao && \
chmod +x /usr/local/bin/yao && \
addgroup -S yao && adduser -S -G yao yao && \
mkdir -p /data/app && \
chown -R yao:yao /data/app
USER yao
VOLUME /data/app
WORKDIR /data/app
EXPOSE 5099
CMD ["/usr/local/bin/yao", "start"]

View file

@ -18,7 +18,7 @@ FROM alpine:latest
ARG VERSION
ARG ARCH
RUN apk --no-cache add curl
RUN curl -fsSL "https://pub-80136338e60643edbb55c6ca8a689cf8.r2.dev/archives/yao-${VERSION}-linux-${ARCH}" > /usr/local/bin/yao && \
RUN curl -fsSL "https://pub-80136338e60643edbb55c6ca8a689cf8.r2.dev/archives/yao-${VERSION}-linux-${ARCH}-prod" > /usr/local/bin/yao && \
chmod +x /usr/local/bin/yao && \
addgroup -S yao && adduser -S -G yao yao && \
mkdir -p /data/app && \