From b970d66bc091b44b29ee0781888eb5b253b78aa6 Mon Sep 17 00:00:00 2001 From: NanamiAdmin Date: Thu, 10 Sep 2026 20:59:21 +0800 Subject: [PATCH] feat(build): add scripts for building frontend and backend for Linux and Windows --- .github/workflows/build.yml | 79 +++++++++++++++++++++++++++++++++ build-linux-x86_64.bat | 87 +++++++++++++++++++++++-------------- build-linux-x86_64.sh | 44 +++++++++++++++++++ build-win-x86_64.bat | 87 +++++++++++++++++++++++-------------- build-win-x86_64.sh | 44 +++++++++++++++++++ 5 files changed, 275 insertions(+), 66 deletions(-) create mode 100644 .github/workflows/build.yml create mode 100644 build-linux-x86_64.sh create mode 100644 build-win-x86_64.sh diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..13f2c5f --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,79 @@ +name: Build + +on: + push: + branches: [main] + pull_request: + workflow_dispatch: + +# A newer push to the same ref makes an in-flight build obsolete. +concurrency: + group: build-${{ github.ref }} + cancel-in-progress: true + +permissions: + contents: read + +jobs: + build: + name: ${{ matrix.os }} + runs-on: ${{ matrix.os }} + strategy: + # Let both platforms finish, so a failure on one still reports the other. + fail-fast: false + matrix: + include: + # The .sh scripts are run through `bash` because a checkout made on + # Windows does not carry the executable bit, so ./build-*.sh would + # come back as "Permission denied" on the Linux runner. + - os: ubuntu-latest + build_linux: bash build-linux-x86_64.sh + build_windows: bash build-win-x86_64.sh + - os: windows-latest + build_linux: ./build-linux-x86_64.bat + build_windows: ./build-win-x86_64.bat + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version-file: go.mod + cache: true + + - name: Set up Node + uses: actions/setup-node@v4 + with: + node-version: 22 + cache: npm + cache-dependency-path: frontend/package-lock.json + + # --frontend builds the Vue app inside the script. The second call omits + # it: the frontend is platform independent and dist/ is already built. + - name: Build Linux (amd64) + run: ${{ matrix.build_linux }} --frontend + + - name: Build Windows (amd64) + run: ${{ matrix.build_windows }} + + - name: Upload binaries + uses: actions/upload-artifact@v4 + with: + name: nukumizu-binaries-${{ matrix.os }} + path: | + nukumizu-linux-amd64 + nukumizu-windows-amd64.exe + if-no-files-found: error + + # The binaries read frontend/dist at runtime (os.DirFS in web/embed.go), + # they do not embed it. Uploaded once — the frontend is platform + # independent, so both matrix legs produce the same files. + - name: Upload frontend bundle + if: runner.os == 'Linux' + uses: actions/upload-artifact@v4 + with: + name: nukumizu-frontend + path: frontend/dist + if-no-files-found: error diff --git a/build-linux-x86_64.bat b/build-linux-x86_64.bat index 6c1980f..62733d5 100644 --- a/build-linux-x86_64.bat +++ b/build-linux-x86_64.bat @@ -1,33 +1,54 @@ -@echo off -setlocal enabledelayedexpansion - -echo Building for Linux (amd64)... - -:: Get git commit hash (shortened to 7 characters, can also use full) -for /f %%i in ('git rev-parse --short HEAD') do set COMMIT=%%i - -:: Get UTC time -for /f %%i in ('powershell -Command "Get-Date -Format 'yyyy-MM-ddTHH:mm:ssZ'"') do set BUILD_DATE=%%i - -:: Set environment variables for Linux build -set GOOS=linux -set GOARCH=amd64 -set CGO_ENABLED=0 - -:: Build -ldflags -set LDFLAGS=-X main.BuildTime=%BUILD_DATE% -X main.CommitHash=%COMMIT% - -:: Set output file name -set OUTPUT=nukumizu-linux-amd64 - -echo Commit: %COMMIT% -echo BuildDate: %BUILD_DATE% -echo Output: %OUTPUT% - -go build -ldflags "%LDFLAGS%" -o "%OUTPUT%" . - -if %errorlevel% equ 0 ( - echo Build succeeded: %OUTPUT% -) else ( - echo Build failed. -) \ No newline at end of file +@echo off +setlocal enabledelayedexpansion + +:: Build from the repository root, however the script was invoked. +cd /d "%~dp0" + +:: Optional first argument: --frontend also builds the Vue frontend, which web/ +:: serves at runtime from frontend/dist. Omitted, only the backend is compiled. +set BUILD_FRONTEND=0 +if /i "%~1"=="--frontend" set BUILD_FRONTEND=1 + +if not "%BUILD_FRONTEND%"=="1" goto :backend + +echo Building frontend... +cd frontend +call npm ci +if errorlevel 1 goto :fail +call npm run build +if errorlevel 1 goto :fail +cd .. + +:backend +echo Building for Linux (amd64)... + +:: Get git commit hash (shortened to 7 characters, can also use full) +for /f %%i in ('git rev-parse --short HEAD') do set COMMIT=%%i + +:: Get UTC time +for /f %%i in ('powershell -Command "(Get-Date).ToUniversalTime().ToString('yyyy-MM-ddTHH:mm:ssZ')"') do set BUILD_DATE=%%i + +:: Set environment variables for Linux build +set GOOS=linux +set GOARCH=amd64 +set CGO_ENABLED=0 + +:: Build -ldflags +set LDFLAGS=-X main.BuildTime=%BUILD_DATE% -X main.CommitHash=%COMMIT% + +:: Set output file name +set OUTPUT=nukumizu-linux-amd64 + +echo Commit: %COMMIT% +echo BuildDate: %BUILD_DATE% +echo Output: %OUTPUT% + +go build -ldflags "%LDFLAGS%" -o "%OUTPUT%" . +if errorlevel 1 goto :fail + +echo Build succeeded: %OUTPUT% +exit /b 0 + +:fail +echo Build failed. +exit /b 1 diff --git a/build-linux-x86_64.sh b/build-linux-x86_64.sh new file mode 100644 index 0000000..25bdd90 --- /dev/null +++ b/build-linux-x86_64.sh @@ -0,0 +1,44 @@ +#!/usr/bin/env bash +# +# Builds the Linux (amd64) binary. +# ./build-linux-x86_64.sh backend only +# ./build-linux-x86_64.sh --frontend also build the Vue frontend +# +# The frontend is needed at runtime: web/ serves it from frontend/dist. +set -euo pipefail + +# Build from the repository root, however the script was invoked. +cd "$(dirname "$0")" + +BUILD_FRONTEND=0 +if [ "${1:-}" = "--frontend" ]; then + BUILD_FRONTEND=1 +fi + +if [ "$BUILD_FRONTEND" = "1" ]; then + echo "Building frontend..." + ( + cd frontend + npm ci + npm run build + ) +fi + +echo "Building for Linux (amd64)..." + +COMMIT=$(git rev-parse --short HEAD) +BUILD_DATE=$(date -u +"%Y-%m-%dT%H:%M:%SZ") + +export GOOS=linux +export GOARCH=amd64 +export CGO_ENABLED=0 + +OUTPUT=nukumizu-linux-amd64 + +echo "Commit: $COMMIT" +echo "BuildDate: $BUILD_DATE" +echo "Output: $OUTPUT" + +go build -ldflags "-X main.BuildTime=$BUILD_DATE -X main.CommitHash=$COMMIT" -o "$OUTPUT" . + +echo "Build succeeded: $OUTPUT" diff --git a/build-win-x86_64.bat b/build-win-x86_64.bat index 1be7130..2cb2353 100644 --- a/build-win-x86_64.bat +++ b/build-win-x86_64.bat @@ -1,33 +1,54 @@ -@echo off -setlocal enabledelayedexpansion - -echo Building for Windows (amd64)... - -:: Get git commit hash (shortened to 7 characters, can also use full) -for /f %%i in ('git rev-parse --short HEAD') do set COMMIT=%%i - -:: Get UTC time -for /f %%i in ('powershell -Command "Get-Date -Format 'yyyy-MM-ddTHH:mm:ssZ'"') do set BUILD_DATE=%%i - -:: Set environment variables for Windows build -set GOOS=windows -set GOARCH=amd64 -set CGO_ENABLED=0 - -:: Build -ldflags -set LDFLAGS=-X main.BuildTime=%BUILD_DATE% -X main.CommitHash=%COMMIT% - -:: Set output file name -set OUTPUT=nukumizu-windows-amd64.exe - -echo Commit: %COMMIT% -echo BuildDate: %BUILD_DATE% -echo Output: %OUTPUT% - -go build -ldflags "%LDFLAGS%" -o "%OUTPUT%" . - -if %errorlevel% equ 0 ( - echo Build succeeded: %OUTPUT% -) else ( - echo Build failed. -) \ No newline at end of file +@echo off +setlocal enabledelayedexpansion + +:: Build from the repository root, however the script was invoked. +cd /d "%~dp0" + +:: Optional first argument: --frontend also builds the Vue frontend, which web/ +:: serves at runtime from frontend/dist. Omitted, only the backend is compiled. +set BUILD_FRONTEND=0 +if /i "%~1"=="--frontend" set BUILD_FRONTEND=1 + +if not "%BUILD_FRONTEND%"=="1" goto :backend + +echo Building frontend... +cd frontend +call npm ci +if errorlevel 1 goto :fail +call npm run build +if errorlevel 1 goto :fail +cd .. + +:backend +echo Building for Windows (amd64)... + +:: Get git commit hash (shortened to 7 characters, can also use full) +for /f %%i in ('git rev-parse --short HEAD') do set COMMIT=%%i + +:: Get UTC time +for /f %%i in ('powershell -Command "(Get-Date).ToUniversalTime().ToString('yyyy-MM-ddTHH:mm:ssZ')"') do set BUILD_DATE=%%i + +:: Set environment variables for Windows build +set GOOS=windows +set GOARCH=amd64 +set CGO_ENABLED=0 + +:: Build -ldflags +set LDFLAGS=-X main.BuildTime=%BUILD_DATE% -X main.CommitHash=%COMMIT% + +:: Set output file name +set OUTPUT=nukumizu-windows-amd64.exe + +echo Commit: %COMMIT% +echo BuildDate: %BUILD_DATE% +echo Output: %OUTPUT% + +go build -ldflags "%LDFLAGS%" -o "%OUTPUT%" . +if errorlevel 1 goto :fail + +echo Build succeeded: %OUTPUT% +exit /b 0 + +:fail +echo Build failed. +exit /b 1 diff --git a/build-win-x86_64.sh b/build-win-x86_64.sh new file mode 100644 index 0000000..86f9a32 --- /dev/null +++ b/build-win-x86_64.sh @@ -0,0 +1,44 @@ +#!/usr/bin/env bash +# +# Builds the Windows (amd64) binary. +# ./build-win-x86_64.sh backend only +# ./build-win-x86_64.sh --frontend also build the Vue frontend +# +# The frontend is needed at runtime: web/ serves it from frontend/dist. +set -euo pipefail + +# Build from the repository root, however the script was invoked. +cd "$(dirname "$0")" + +BUILD_FRONTEND=0 +if [ "${1:-}" = "--frontend" ]; then + BUILD_FRONTEND=1 +fi + +if [ "$BUILD_FRONTEND" = "1" ]; then + echo "Building frontend..." + ( + cd frontend + npm ci + npm run build + ) +fi + +echo "Building for Windows (amd64)..." + +COMMIT=$(git rev-parse --short HEAD) +BUILD_DATE=$(date -u +"%Y-%m-%dT%H:%M:%SZ") + +export GOOS=windows +export GOARCH=amd64 +export CGO_ENABLED=0 + +OUTPUT=nukumizu-windows-amd64.exe + +echo "Commit: $COMMIT" +echo "BuildDate: $BUILD_DATE" +echo "Output: $OUTPUT" + +go build -ldflags "-X main.BuildTime=$BUILD_DATE -X main.CommitHash=$COMMIT" -o "$OUTPUT" . + +echo "Build succeeded: $OUTPUT"