build.yml 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667
  1. name: Build
  2. on:
  3. push:
  4. branches-ignore:
  5. - 'weblate'
  6. paths:
  7. - "app/**/*.js"
  8. - "app/**/*.ts"
  9. - "app/**/*.vue"
  10. - "app/src/language/**/*.po"
  11. - "app/i18n.json"
  12. - "app/package.json"
  13. - "app/.env*"
  14. - "**/*.go"
  15. - "go.mod"
  16. - "go.sum"
  17. - ".github/workflows/build*.yml"
  18. - "resources/docker/docker/*"
  19. - "resources/development/*"
  20. - "resources/demo/*"
  21. - "Dockerfile"
  22. - "demo.Dockerfile"
  23. pull_request:
  24. types: [ opened, synchronize, reopened ]
  25. paths:
  26. - "**/*.js"
  27. - "**/*.vue"
  28. - "app/package.json"
  29. - "app/.env*"
  30. - "**/*.go"
  31. - "go.mod"
  32. - "go.sum"
  33. - ".github/workflows/*.yml"
  34. - "resources/docker/docker/*"
  35. - "resources/development/*"
  36. - "resources/demo/*"
  37. release:
  38. types:
  39. - published
  40. jobs:
  41. build_app:
  42. runs-on: macos-latest
  43. steps:
  44. - name: Checkout
  45. uses: actions/checkout@v5
  46. - name: Set up nodejs
  47. uses: actions/setup-node@v6
  48. with:
  49. node-version: current
  50. - name: Install dependencies
  51. run: |
  52. corepack enable
  53. corepack prepare pnpm@latest --activate
  54. pnpm install
  55. - name: Check frontend code style
  56. run: |
  57. pnpm lint
  58. - name: Check frontend types
  59. run: |
  60. pnpm typecheck
  61. - name: Build
  62. run: |
  63. npx update-browserslist-db@latest
  64. pnpm build
  65. - name: Compress frontend with xz
  66. run: |
  67. # Create compressed archive of the entire dist directory
  68. tar -C app -cf - dist | xz -9 -c > app/dist.tar.xz
  69. # Verify compression worked and show savings (macOS compatible)
  70. ORIGINAL_SIZE=$(find app/dist -type f -exec stat -f%z {} \; | awk '{total += $1} END {print total}')
  71. COMPRESSED_SIZE=$(stat -f%z app/dist.tar.xz)
  72. if [[ $ORIGINAL_SIZE -gt 0 ]]; then
  73. SAVINGS=$((100 - COMPRESSED_SIZE * 100 / ORIGINAL_SIZE))
  74. echo "Original size: ${ORIGINAL_SIZE} bytes"
  75. echo "Compressed size: ${COMPRESSED_SIZE} bytes"
  76. echo "Compression savings: ${SAVINGS}%"
  77. else
  78. echo "Compressed size: ${COMPRESSED_SIZE} bytes"
  79. fi
  80. - name: Archive app artifacts
  81. uses: actions/upload-artifact@v5
  82. with:
  83. name: app-dist
  84. path: |
  85. app/dist.tar.xz
  86. - name: Prepare publish
  87. if: github.event_name == 'release'
  88. run: |
  89. cp README*.md app/dist
  90. find app/dist -printf '%P\n' | tar -C app/dist --no-recursion -zcvf app-dist.tar.gz -T -
  91. - name: Publish
  92. uses: softprops/action-gh-release@v2
  93. if: github.event_name == 'release'
  94. with:
  95. files: app-dist.tar.gz
  96. build:
  97. runs-on: ubuntu-latest
  98. needs: build_app
  99. strategy:
  100. matrix:
  101. goos: [ linux, windows ]
  102. goarch: [ amd64, 386, arm64 ]
  103. # exclude:
  104. # Exclude i386 on windows (if needed)
  105. # - goarch: 386
  106. # goos: windows
  107. include:
  108. # BEGIN Linux ARM 5 6 7
  109. - goos: linux
  110. goarch: arm
  111. goarm: 7
  112. - goos: linux
  113. goarch: arm
  114. goarm: 6
  115. - goos: linux
  116. goarch: arm
  117. goarm: 5
  118. # END Linux ARM 5 6 7
  119. - goos: linux
  120. goarch: riscv64
  121. - goos: linux
  122. goarch: loong64
  123. # BEGIN MIPS
  124. - goos: linux
  125. goarch: mips64
  126. - goos: linux
  127. goarch: mips64le
  128. - goos: linux
  129. goarch: mipsle
  130. - goos: linux
  131. goarch: mips
  132. # END MIPS
  133. env:
  134. CGO_ENABLED: 1
  135. GOOS: ${{ matrix.goos }}
  136. GOARCH: ${{ matrix.goarch }}
  137. GOARM: ${{ matrix.goarm }}
  138. steps:
  139. - name: Checkout
  140. uses: actions/checkout@v5
  141. - name: Set up Go
  142. uses: actions/setup-go@v6
  143. with:
  144. go-version: ^1.25.4
  145. cache: false
  146. - name: Setup environment
  147. id: info
  148. run: |
  149. export _NAME=$(jq ".$GOOS[\"$GOARCH$GOARM\"].name" -r < .github/build/build_info.json)
  150. export _ARCH=$(jq ".$GOOS[\"$GOARCH$GOARM\"].arch" -r < .github/build/build_info.json)
  151. export _ABI=$(jq ".$GOOS[\"$GOARCH$GOARM\"].abi // \"\"" -r < .github/build/build_info.json)
  152. export _ARTIFACT=nginx-ui-$GOOS-$GOARCH$(if [[ "$GOARM" ]]; then echo "v$GOARM"; fi)
  153. export _BINARY=nginx-ui$(if [[ "$GOOS" == "windows" ]]; then echo ".exe"; fi)
  154. echo "GOOS: $GOOS, GOARCH: $GOARCH, GOARM: $GOARM, ABI: $_ABI, RELEASE_NAME: $_NAME, ARTIFACT_NAME: $_ARTIFACT, BINARY_NAME: $_BINARY"
  155. echo "CACHE_NAME=$_NAME" >> $GITHUB_ENV
  156. echo "ARCH_NAME=$_ARCH" >> $GITHUB_ENV
  157. echo "ABI=$_ABI" >> $GITHUB_ENV
  158. echo "DIST=nginx-ui-$_NAME" >> $GITHUB_ENV
  159. echo "ARTIFACT=$_ARTIFACT" >> $GITHUB_ENV
  160. echo "BINARY_NAME=$_BINARY" >> $GITHUB_ENV
  161. - name: Setup Go modules cache
  162. uses: actions/cache@v4
  163. with:
  164. path: |
  165. ~/go/pkg/mod
  166. key: go-${{ runner.os }}-${{ runner.arch }}-mod-${{ hashFiles('go.mod') }}
  167. restore-keys: |
  168. go-${{ runner.os }}-${{ runner.arch }}-mod-
  169. - name: Setup Go build cache
  170. uses: actions/cache@v4
  171. with:
  172. path: |
  173. ~/.cache/go-build
  174. key: go-${{ runner.os }}-${{ runner.arch }}-${{ env.CACHE_NAME }}-${{ hashFiles('go.mod') }}
  175. restore-keys: |
  176. go-${{ runner.os }}-${{ runner.arch }}-${{ env.CACHE_NAME }}-
  177. - name: Download app artifacts
  178. uses: actions/download-artifact@v6
  179. with:
  180. name: app-dist
  181. path: app/dist.tar.xz
  182. - name: Generate files
  183. env:
  184. GOOS: linux
  185. GOARCH: amd64
  186. run: go generate cmd/version/generate.go
  187. - name: Install musl cross compiler
  188. if: env.GOOS == 'linux'
  189. uses: nginxui/musl-cross-compilers@v1
  190. id: musl
  191. with:
  192. target: ${{ env.ARCH_NAME }}-linux-musl${{ env.ABI }}
  193. variant: ${{ env.GOARCH == 'loong64' && 'userdocs/qbt-musl-cross-make' || 'richfelker/musl-cross-make' }}
  194. - name: Post install musl cross compiler
  195. if: env.GOOS == 'linux'
  196. run: |
  197. echo "PATH=${{ steps.musl.outputs.path }}:$PATH" >> $GITHUB_ENV
  198. echo "CC=${{ env.ARCH_NAME }}-linux-musl${{ env.ABI }}-gcc" >> $GITHUB_ENV
  199. echo "CXX=${{ env.ARCH_NAME }}-linux-musl${{ env.ABI }}-g++" >> $GITHUB_ENV
  200. echo "LD_FLAGS=-w --extldflags '-static'" >> $GITHUB_ENV
  201. - name: Setup for Windows
  202. if: env.GOOS == 'windows'
  203. run: |
  204. echo "LD_FLAGS=-w" >> $GITHUB_ENV
  205. echo "CGO_ENABLED=1" >> $GITHUB_ENV
  206. # Install cross compilers based on architecture
  207. sudo apt-get update
  208. sudo apt-get install -y zip
  209. if [[ "$GOARCH" == "amd64" ]]; then
  210. echo "Installing x86_64 Windows cross compiler"
  211. sudo apt-get install -y gcc-mingw-w64-x86-64 g++-mingw-w64-x86-64
  212. echo "CC=x86_64-w64-mingw32-gcc" >> $GITHUB_ENV
  213. echo "CXX=x86_64-w64-mingw32-g++" >> $GITHUB_ENV
  214. elif [[ "$GOARCH" == "386" ]]; then
  215. echo "Installing i686 Windows cross compiler"
  216. sudo apt-get install -y gcc-mingw-w64-i686 g++-mingw-w64-i686
  217. echo "CC=i686-w64-mingw32-gcc" >> $GITHUB_ENV
  218. echo "CXX=i686-w64-mingw32-g++" >> $GITHUB_ENV
  219. elif [[ "$GOARCH" == "arm64" ]]; then
  220. echo "Installing ARM64 Windows cross compiler"
  221. # Ubuntu's apt repositories don't have mingw for ARM64
  222. # Use llvm-mingw project instead
  223. mkdir -p $HOME/llvm-mingw
  224. wget -q https://github.com/mstorsjo/llvm-mingw/releases/download/20231128/llvm-mingw-20231128-ucrt-ubuntu-20.04-x86_64.tar.xz
  225. tar xf llvm-mingw-20231128-ucrt-ubuntu-20.04-x86_64.tar.xz -C $HOME/llvm-mingw --strip-components=1
  226. echo "PATH=$HOME/llvm-mingw/bin:$PATH" >> $GITHUB_ENV
  227. echo "CC=aarch64-w64-mingw32-clang" >> $GITHUB_ENV
  228. echo "CXX=aarch64-w64-mingw32-clang++" >> $GITHUB_ENV
  229. else
  230. echo "Unsupported Windows architecture: $GOARCH"
  231. exit 1
  232. fi
  233. - name: Build
  234. run: |
  235. mkdir -p dist
  236. go build -trimpath -tags=jsoniter -ldflags "$LD_FLAGS -X 'github.com/0xJacky/Nginx-UI/settings.buildTime=$(date +%s)'" -o dist/$BINARY_NAME -v main.go
  237. - name: Archive backend artifacts
  238. uses: actions/upload-artifact@v5
  239. with:
  240. name: ${{ env.ARTIFACT }}
  241. path: dist/${{ env.BINARY_NAME }}
  242. - name: Prepare publish
  243. run: |
  244. cp README*.md ./dist
  245. find dist -printf '%P\n' | tar -C dist --no-recursion -zcvf ${{ env.DIST }}.tar.gz -T -
  246. openssl dgst -sha512 ${{ env.DIST }}.tar.gz | sed 's/([^)]*)//g' | awk '{print $NF}' >> ${{ env.DIST }}.tar.gz.digest
  247. # Create zip for Windows builds (for winget compatibility)
  248. if [[ "$GOOS" == "windows" ]]; then
  249. cd dist
  250. zip -r ../${{ env.DIST }}.zip .
  251. cd ..
  252. openssl dgst -sha512 ${{ env.DIST }}.zip | sed 's/([^)]*)//g' | awk '{print $NF}' >> ${{ env.DIST }}.zip.digest
  253. fi
  254. - name: Publish
  255. uses: softprops/action-gh-release@v2
  256. if: github.event_name == 'release'
  257. with:
  258. files: |
  259. ${{ env.DIST }}.tar.gz
  260. ${{ env.DIST }}.tar.gz.digest
  261. ${{ env.GOOS == 'windows' && format('{0}.zip', env.DIST) || '' }}
  262. ${{ env.GOOS == 'windows' && format('{0}.zip.digest', env.DIST) || '' }}
  263. - name: Upload to R2 using S3 API
  264. if: github.event_name != 'pull_request' && github.ref == 'refs/heads/dev'
  265. env:
  266. AWS_ACCESS_KEY_ID: ${{ secrets.R2_ACCESS_KEY_ID }}
  267. AWS_SECRET_ACCESS_KEY: ${{ secrets.R2_SECRET_ACCESS_KEY }}
  268. AWS_REGION: us-east-1
  269. run: |
  270. echo "Uploading ${{ env.DIST }}.tar.gz to R2..."
  271. aws s3 cp ./${{ env.DIST }}.tar.gz s3://nginx-ui-dev-build/${{ env.DIST }}.tar.gz --endpoint-url=${{ secrets.R2_S3_API_ENDPOINT }}
  272. echo "Uploading ${{ env.DIST }}.tar.gz.digest to R2..."
  273. aws s3 cp ./${{ env.DIST }}.tar.gz.digest s3://nginx-ui-dev-build/${{ env.DIST }}.tar.gz.digest --endpoint-url=${{ secrets.R2_S3_API_ENDPOINT }}
  274. echo "Upload completed successfully"
  275. build_macos_native:
  276. runs-on: macos-latest
  277. needs: build_app
  278. strategy:
  279. matrix:
  280. goarch: [amd64, arm64]
  281. env:
  282. CGO_ENABLED: 1
  283. GOOS: darwin
  284. GOARCH: ${{ matrix.goarch }}
  285. steps:
  286. - name: Checkout
  287. uses: actions/checkout@v5
  288. - name: Set up Go
  289. uses: actions/setup-go@v6
  290. with:
  291. go-version: ^1.25.4
  292. cache: false
  293. - name: Setup environment
  294. id: info
  295. run: |
  296. export _NAME=$(jq ".darwin[\"$GOARCH\"].name" -r < .github/build/build_info.json)
  297. export _ARTIFACT=nginx-ui-darwin-$GOARCH
  298. export _BINARY=nginx-ui
  299. echo "GOOS: darwin, GOARCH: $GOARCH, RELEASE_NAME: $_NAME, ARTIFACT_NAME: $_ARTIFACT, BINARY_NAME: $_BINARY"
  300. echo "CACHE_NAME=$_NAME" >> $GITHUB_ENV
  301. echo "DIST=nginx-ui-$_NAME" >> $GITHUB_ENV
  302. echo "ARTIFACT=$_ARTIFACT" >> $GITHUB_ENV
  303. echo "BINARY_NAME=$_BINARY" >> $GITHUB_ENV
  304. - name: Setup Go build cache
  305. uses: actions/cache@v4
  306. with:
  307. path: |
  308. ~/go/pkg/mod
  309. ~/.cache/go-build
  310. key: go-${{ runner.os }}-${{ runner.arch }}-${{ env.CACHE_NAME }}-${{ hashFiles('go.mod') }}
  311. restore-keys: |
  312. go-${{ runner.os }}-${{ runner.arch }}-${{ env.CACHE_NAME }}-
  313. - name: Download app artifacts
  314. uses: actions/download-artifact@v6
  315. with:
  316. name: app-dist
  317. path: app/dist.tar.xz
  318. - name: Generate files
  319. run: go generate cmd/version/generate.go
  320. - name: Build with native CGO
  321. run: |
  322. mkdir -p dist
  323. go build -trimpath -tags=jsoniter -ldflags "-w -X 'github.com/0xJacky/Nginx-UI/settings.buildTime=$(date +%s)'" -o dist/$BINARY_NAME -v main.go
  324. - name: Archive backend artifacts
  325. uses: actions/upload-artifact@v5
  326. with:
  327. name: ${{ env.ARTIFACT }}
  328. path: dist/${{ env.BINARY_NAME }}
  329. - name: Prepare publish
  330. run: |
  331. cp README*.md ./dist
  332. cd dist && tar -zcvf ../${{ env.DIST }}.tar.gz .
  333. cd ..
  334. openssl dgst -sha512 ${{ env.DIST }}.tar.gz | sed 's/([^)]*)//g' | awk '{print $NF}' >> ${{ env.DIST }}.tar.gz.digest
  335. - name: Publish
  336. uses: softprops/action-gh-release@v2
  337. if: github.event_name == 'release'
  338. with:
  339. files: |
  340. ${{ env.DIST }}.tar.gz
  341. ${{ env.DIST }}.tar.gz.digest
  342. - name: Upload to R2 using S3 API
  343. if: github.event_name != 'pull_request' && github.ref == 'refs/heads/dev'
  344. env:
  345. AWS_ACCESS_KEY_ID: ${{ secrets.R2_ACCESS_KEY_ID }}
  346. AWS_SECRET_ACCESS_KEY: ${{ secrets.R2_SECRET_ACCESS_KEY }}
  347. AWS_REGION: us-east-1
  348. run: |
  349. echo "Uploading ${{ env.DIST }}.tar.gz to R2..."
  350. aws s3 cp ./${{ env.DIST }}.tar.gz s3://nginx-ui-dev-build/${{ env.DIST }}.tar.gz --endpoint-url=${{ secrets.R2_S3_API_ENDPOINT }}
  351. echo "Uploading ${{ env.DIST }}.tar.gz.digest to R2..."
  352. aws s3 cp ./${{ env.DIST }}.tar.gz.digest s3://nginx-ui-dev-build/${{ env.DIST }}.tar.gz.digest --endpoint-url=${{ secrets.R2_S3_API_ENDPOINT }}
  353. echo "Upload completed successfully"
  354. docker-build:
  355. if: github.event_name != 'pull_request'
  356. runs-on: ubuntu-latest
  357. needs: [build, build_macos_native]
  358. env:
  359. PLATFORMS: linux/amd64,linux/arm64,linux/arm/v7,linux/arm/v6,linux/arm/v5
  360. steps:
  361. - name: Checkout
  362. uses: actions/checkout@v5
  363. - name: Docker meta
  364. id: meta
  365. uses: docker/metadata-action@v5
  366. with:
  367. images: |
  368. uozi/nginx-ui
  369. tags: |
  370. type=schedule
  371. type=ref,event=branch
  372. type=semver,pattern={{version}}
  373. type=semver,pattern={{raw}}
  374. type=sha
  375. type=raw,value=latest,enable=${{ github.event_name == 'release' && !github.event.release.prerelease }}
  376. - name: Download artifacts
  377. uses: actions/download-artifact@v6
  378. with:
  379. path: ./dist
  380. - name: Prepare Artifacts
  381. run: chmod +x ./dist/nginx-ui-*/nginx-ui*
  382. - name: Set up Docker Buildx
  383. id: buildx
  384. uses: docker/setup-buildx-action@v3
  385. - name: Login to DockerHub
  386. uses: docker/login-action@v3
  387. with:
  388. username: ${{ secrets.DOCKERHUB_USER }}
  389. password: ${{ secrets.DOCKERHUB_TOKEN }}
  390. - name: Prepare Dockerfile
  391. run: |
  392. cp ./Dockerfile ./dist
  393. cp -rp ./resources ./dist
  394. - name: Build and push
  395. uses: docker/build-push-action@v6
  396. with:
  397. context: ./dist
  398. file: ./dist/Dockerfile
  399. platforms: ${{ env.PLATFORMS }}
  400. push: ${{ github.event_name != 'pull_request' }}
  401. tags: ${{ steps.meta.outputs.tags }}
  402. labels: ${{ steps.meta.outputs.labels }}
  403. - name: Prepare Demo Dockerfile
  404. run: |
  405. cp ./demo.Dockerfile ./dist
  406. cp -rp ./resources ./dist
  407. - name: Build and push demo
  408. uses: docker/build-push-action@v6
  409. if: github.ref == 'refs/heads/dev'
  410. with:
  411. context: ./dist
  412. file: ./dist/demo.Dockerfile
  413. platforms: ${{ env.PLATFORMS }}
  414. push: 'true'
  415. tags: |
  416. uozi/nginx-ui-demo:latest
  417. update-homebrew:
  418. runs-on: ubuntu-latest
  419. needs: [build, build_macos_native]
  420. if: github.event_name == 'release'
  421. steps:
  422. - name: Checkout
  423. uses: actions/checkout@v5
  424. - name: Get release info
  425. id: release
  426. run: |
  427. echo "tag_name=${{ github.event.release.tag_name }}" >> $GITHUB_OUTPUT
  428. echo "version=${GITHUB_REF#refs/tags/v}" >> $GITHUB_OUTPUT
  429. - name: Download release assets and calculate SHA256 checksums
  430. id: checksums
  431. run: |
  432. VERSION="${{ steps.release.outputs.version }}"
  433. TAG_NAME="${{ steps.release.outputs.tag_name }}"
  434. # Download binary files from releases and calculate SHA256
  435. mkdir -p downloads
  436. # macOS Intel
  437. wget -O downloads/nginx-ui-macos-64.tar.gz "https://github.com/${{ github.repository }}/releases/download/$TAG_NAME/nginx-ui-macos-64.tar.gz"
  438. MACOS_INTEL_SHA256=$(sha256sum downloads/nginx-ui-macos-64.tar.gz | cut -d' ' -f1)
  439. # macOS ARM
  440. wget -O downloads/nginx-ui-macos-arm64-v8a.tar.gz "https://github.com/${{ github.repository }}/releases/download/$TAG_NAME/nginx-ui-macos-arm64-v8a.tar.gz"
  441. MACOS_ARM_SHA256=$(sha256sum downloads/nginx-ui-macos-arm64-v8a.tar.gz | cut -d' ' -f1)
  442. # Linux Intel
  443. wget -O downloads/nginx-ui-linux-64.tar.gz "https://github.com/${{ github.repository }}/releases/download/$TAG_NAME/nginx-ui-linux-64.tar.gz"
  444. LINUX_INTEL_SHA256=$(sha256sum downloads/nginx-ui-linux-64.tar.gz | cut -d' ' -f1)
  445. # Linux ARM
  446. wget -O downloads/nginx-ui-linux-arm64-v8a.tar.gz "https://github.com/${{ github.repository }}/releases/download/$TAG_NAME/nginx-ui-linux-arm64-v8a.tar.gz"
  447. LINUX_ARM_SHA256=$(sha256sum downloads/nginx-ui-linux-arm64-v8a.tar.gz | cut -d' ' -f1)
  448. echo "macos_intel_sha256=$MACOS_INTEL_SHA256" >> $GITHUB_OUTPUT
  449. echo "macos_arm_sha256=$MACOS_ARM_SHA256" >> $GITHUB_OUTPUT
  450. echo "linux_intel_sha256=$LINUX_INTEL_SHA256" >> $GITHUB_OUTPUT
  451. echo "linux_arm_sha256=$LINUX_ARM_SHA256" >> $GITHUB_OUTPUT
  452. - name: Generate Homebrew Formula
  453. id: formula
  454. run: |
  455. VERSION="${{ steps.release.outputs.version }}"
  456. cat > nginx-ui.rb << 'EOF'
  457. class NginxUi < Formula
  458. desc "Yet another Nginx Web UI"
  459. homepage "https://github.com/0xJacky/nginx-ui"
  460. version "${{ steps.release.outputs.version }}"
  461. license "AGPL-3.0"
  462. on_macos do
  463. on_intel do
  464. url "https://github.com/0xJacky/nginx-ui/releases/download/v#{version}/nginx-ui-macos-64.tar.gz"
  465. sha256 "${{ steps.checksums.outputs.macos_intel_sha256 }}"
  466. end
  467. on_arm do
  468. url "https://github.com/0xJacky/nginx-ui/releases/download/v#{version}/nginx-ui-macos-arm64-v8a.tar.gz"
  469. sha256 "${{ steps.checksums.outputs.macos_arm_sha256 }}"
  470. end
  471. end
  472. on_linux do
  473. on_intel do
  474. url "https://github.com/0xJacky/nginx-ui/releases/download/v#{version}/nginx-ui-linux-64.tar.gz"
  475. sha256 "${{ steps.checksums.outputs.linux_intel_sha256 }}"
  476. end
  477. on_arm do
  478. url "https://github.com/0xJacky/nginx-ui/releases/download/v#{version}/nginx-ui-linux-arm64-v8a.tar.gz"
  479. sha256 "${{ steps.checksums.outputs.linux_arm_sha256 }}"
  480. end
  481. end
  482. def install
  483. bin.install "nginx-ui"
  484. # Create configuration directory
  485. (etc/"nginx-ui").mkpath
  486. # Create default configuration file if it doesn't exist
  487. config_file = etc/"nginx-ui/app.ini"
  488. unless config_file.exist?
  489. config_file.write <<~EOS
  490. [app]
  491. PageSize = 10
  492. [server]
  493. Host = 0.0.0.0
  494. Port = 9000
  495. RunMode = release
  496. [cert]
  497. HTTPChallengePort = 9180
  498. [terminal]
  499. StartCmd = login
  500. EOS
  501. end
  502. # Create data directory
  503. (var/"nginx-ui").mkpath
  504. end
  505. def post_install
  506. # Ensure correct permissions
  507. (var/"nginx-ui").chmod 0755
  508. end
  509. service do
  510. run [opt_bin/"nginx-ui", "serve", "--config", etc/"nginx-ui/app.ini"]
  511. keep_alive true
  512. working_dir var/"nginx-ui"
  513. log_path var/"log/nginx-ui.log"
  514. error_log_path var/"log/nginx-ui.err.log"
  515. end
  516. test do
  517. assert_match version.to_s, shell_output("#{bin}/nginx-ui --version")
  518. end
  519. end
  520. EOF
  521. echo "Generated Homebrew Formula:"
  522. cat nginx-ui.rb
  523. - name: Checkout homebrew-tools repository
  524. uses: actions/checkout@v5
  525. with:
  526. repository: 0xJacky/homebrew-tools
  527. path: homebrew-tools
  528. token: ${{ secrets.HOMEBREW_GITHUB_TOKEN }}
  529. - name: Update Formula file
  530. run: |
  531. # Copy the generated formula to the correct location
  532. mkdir -p homebrew-tools/Formula/
  533. cp nginx-ui.rb homebrew-tools/Formula/nginx-ui.rb
  534. - name: Verify Formula
  535. run: |
  536. cd homebrew-tools
  537. # Basic syntax check
  538. ruby -c Formula/nginx-ui.rb
  539. echo "Formula syntax is valid"
  540. - name: Create Pull Request to homebrew-tools
  541. uses: peter-evans/create-pull-request@v7
  542. with:
  543. token: ${{ secrets.HOMEBREW_GITHUB_TOKEN }}
  544. path: homebrew-tools
  545. branch: update-nginx-ui-${{ steps.release.outputs.version }}
  546. delete-branch: true
  547. title: 'nginx-ui ${{ steps.release.outputs.version }}'
  548. body: |
  549. Update nginx-ui to version ${{ steps.release.outputs.version }}
  550. **Release Notes:**
  551. - Version: ${{ steps.release.outputs.version }}
  552. - Release URL: https://github.com/${{ github.repository }}/releases/tag/${{ steps.release.outputs.tag_name }}
  553. **Checksums (SHA256):**
  554. - macOS Intel: ${{ steps.checksums.outputs.macos_intel_sha256 }}
  555. - macOS ARM: ${{ steps.checksums.outputs.macos_arm_sha256 }}
  556. - Linux Intel: ${{ steps.checksums.outputs.linux_intel_sha256 }}
  557. - Linux ARM: ${{ steps.checksums.outputs.linux_arm_sha256 }}
  558. ---
  559. This PR was automatically generated by GitHub Actions.
  560. commit-message: 'nginx-ui ${{ steps.release.outputs.version }}'
  561. committer: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
  562. author: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
  563. add-paths: |
  564. Formula/nginx-ui.rb
  565. publish-winget:
  566. runs-on: windows-latest
  567. needs: [build, build_macos_native]
  568. if: github.event_name == 'release'
  569. steps:
  570. - name: Checkout
  571. uses: actions/checkout@v5
  572. - name: Publish to WinGet
  573. uses: vedantmgoyal9/winget-releaser@v2
  574. with:
  575. identifier: 0xJacky.nginx-ui
  576. max-versions-to-keep: 5
  577. token: ${{ secrets.HOMEBREW_GITHUB_TOKEN }}
  578. installers-regex: 'nginx-ui-windows.*\.zip$'