Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| c001f0e8e6 | |||
| f039bd0c61 | |||
| f4beb90769 | |||
| 6f0b273950 | |||
| b43601b4fd | |||
| 3aa63d6575 |
@@ -1,8 +1,9 @@
|
|||||||
name: DB Backup
|
name: DB Backup
|
||||||
|
|
||||||
on:
|
on:
|
||||||
schedule:
|
# 定时备份已暂停(保留手动触发)。恢复时取消下面 schedule 的注释即可。
|
||||||
- cron: '0 18 * * *' # UTC 18:00 = 北京时间 02:00
|
# schedule:
|
||||||
|
# - cron: '0 18 * * *' # UTC 18:00 = 北京时间 02:00
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
|
|||||||
@@ -1,30 +0,0 @@
|
|||||||
name: CI
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches-ignore: [main]
|
|
||||||
pull_request:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
test:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- uses: actions/setup-go@v5
|
|
||||||
with:
|
|
||||||
go-version-file: backend/go.mod
|
|
||||||
cache-dependency-path: backend/go.sum
|
|
||||||
|
|
||||||
- name: Go tests
|
|
||||||
working-directory: backend
|
|
||||||
run: go test ./...
|
|
||||||
|
|
||||||
- uses: subosito/flutter-action@v2
|
|
||||||
with:
|
|
||||||
channel: stable
|
|
||||||
cache: true
|
|
||||||
|
|
||||||
- name: Flutter tests
|
|
||||||
working-directory: client
|
|
||||||
run: flutter test
|
|
||||||
@@ -16,6 +16,9 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Provision (idempotent — auto-runs if host not initialized)
|
||||||
|
run: sh scripts/ci/provision-mac.sh
|
||||||
|
|
||||||
- name: Compile (Linux backend + Flutter Web)
|
- name: Compile (Linux backend + Flutter Web)
|
||||||
run: sh scripts/ci/compile.sh "${{ gitea.ref_name }}"
|
run: sh scripts/ci/compile.sh "${{ gitea.ref_name }}"
|
||||||
|
|
||||||
@@ -26,6 +29,9 @@ jobs:
|
|||||||
path: dist/
|
path: dist/
|
||||||
|
|
||||||
build-macos:
|
build-macos:
|
||||||
|
# Same physical runner as build-linux-web (label: mac, capacity 1). Run them
|
||||||
|
# serially via needs so the second job doesn't sit queued and time out.
|
||||||
|
needs: build-linux-web
|
||||||
runs-on: mac
|
runs-on: mac
|
||||||
env:
|
env:
|
||||||
PUB_HOSTED_URL: https://pub.flutter-io.cn
|
PUB_HOSTED_URL: https://pub.flutter-io.cn
|
||||||
@@ -34,6 +40,9 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Provision (idempotent — auto-runs if host not initialized)
|
||||||
|
run: sh scripts/ci/provision-mac.sh
|
||||||
|
|
||||||
- name: Compile (Flutter macOS)
|
- name: Compile (Flutter macOS)
|
||||||
run: sh scripts/ci/compile-macos.sh "${{ gitea.ref_name }}"
|
run: sh scripts/ci/compile-macos.sh "${{ gitea.ref_name }}"
|
||||||
|
|
||||||
@@ -53,6 +62,10 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Provision (idempotent — auto-runs if host not initialized)
|
||||||
|
shell: bash
|
||||||
|
run: sh scripts/ci/provision-windows.sh
|
||||||
|
|
||||||
- name: Compile (Flutter Windows)
|
- name: Compile (Flutter Windows)
|
||||||
shell: bash
|
shell: bash
|
||||||
run: sh scripts/ci/compile-windows.sh "${{ gitea.ref_name }}"
|
run: sh scripts/ci/compile-windows.sh "${{ gitea.ref_name }}"
|
||||||
|
|||||||
@@ -5,6 +5,41 @@ All notable changes to this project will be documented in this file.
|
|||||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
|
## [1.0.10] - 2026-06-04
|
||||||
|
|
||||||
|
### 新功能
|
||||||
|
- Windows 客户端改为提供安装程序(Inno Setup 打包的 `jiu-windows-x64-setup.exe`,含中文向导、桌面/开始菜单快捷方式、卸载项),不再是解压版 zip
|
||||||
|
|
||||||
|
### 修复
|
||||||
|
- 修复客户端「无法安全下载」:下载地址从内网 HTTP Forgejo(`http://192.168.3.200:3000`,公网不可达且被浏览器拦截)改为同源 HTTPS `https://jiu.51yanmei.com/downloads/...`,Windows、macOS 均生效
|
||||||
|
|
||||||
|
## [1.0.9] - 2026-06-04
|
||||||
|
|
||||||
|
### 修复
|
||||||
|
- 适配 nginx 容器化部署:nginx 已迁入 `pangolin-edge` 容器(host 网络),deploy 改为将 jiu.conf 写入 pangolin 挂载目录并 `docker exec pangolin-edge nginx -s reload`,不再操作已废弃的主机 nginx
|
||||||
|
|
||||||
|
## [1.0.8] - 2026-06-03
|
||||||
|
|
||||||
|
### 修复
|
||||||
|
- 修复 EC2 部署最后一步 nginx reload 失败(`invalid PID number`):改用 `systemctl reload-or-restart nginx`(经 systemd MAINPID 发 HUP,不依赖空的 /run/nginx.pid),并 `enable nginx` 确保重启后自启
|
||||||
|
|
||||||
|
## [1.0.7] - 2026-06-03
|
||||||
|
|
||||||
|
### 修复
|
||||||
|
- 修复 Windows 构建 `PathExistsException`(errno 183):复制 client/ 到 C:\jiu-build 后,先清除 cp 复制成真实目录的插件软链(windows/flutter/ephemeral)及 .dart_tool/build,再交给 flutter 干净重建
|
||||||
|
|
||||||
|
## [1.0.6] - 2026-06-03
|
||||||
|
|
||||||
|
### 改进
|
||||||
|
- CI 运行环境自愈预置:mac/windows runner 首次构建自动 `flutter precache` 并预热 pub/go/npm 缓存(stamp 文件按 Flutter 版本短路),后续构建不再运行时下载 engine
|
||||||
|
- 发版流水线同一 mac runner 上的任务改为串行(build-macos 依赖 build-linux-web),避免排队等待超时失败
|
||||||
|
- 暂停定时数据库备份(保留手动触发)
|
||||||
|
|
||||||
|
## [1.0.5] - 2026-06-03
|
||||||
|
|
||||||
|
### 修复
|
||||||
|
- 修复 Windows CI 构建失败:放弃脆弱的 `subst W:` 路径映射,改为将 client/ 复制到 System32 之外的干净短路径(C:\jiu-build)构建,规避 WOW64 文件系统重定向
|
||||||
|
|
||||||
## [1.0.4] - 2026-05-30
|
## [1.0.4] - 2026-05-30
|
||||||
|
|
||||||
### 新功能
|
### 新功能
|
||||||
|
|||||||
@@ -59,6 +59,14 @@ server {
|
|||||||
try_files /scan.html =404;
|
try_files /scan.html =404;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# 桌面客户端安装包下载(Windows .exe / macOS .zip)
|
||||||
|
location /downloads/ {
|
||||||
|
alias /opt/jiu/downloads/;
|
||||||
|
add_header Content-Disposition "attachment";
|
||||||
|
add_header Cache-Control "no-cache";
|
||||||
|
autoindex off;
|
||||||
|
}
|
||||||
|
|
||||||
# 营销站点兜底(根路径及所有其他路径)
|
# 营销站点兜底(根路径及所有其他路径)
|
||||||
location / {
|
location / {
|
||||||
root /opt/jiu/marketing;
|
root /opt/jiu/marketing;
|
||||||
|
|||||||
@@ -0,0 +1,53 @@
|
|||||||
|
; Inno Setup script for 岩美酒库 Windows 客户端
|
||||||
|
; Compiled in CI:
|
||||||
|
; ISCC /DAppVer=<ver> "/DSrcDir=<ReleaseDir>" "/DOutDir=<dist>" jiu-installer.iss
|
||||||
|
; Produces: <OutDir>\jiu-windows-x64-setup.exe
|
||||||
|
|
||||||
|
#ifndef AppVer
|
||||||
|
#define AppVer "0.0.0"
|
||||||
|
#endif
|
||||||
|
#ifndef SrcDir
|
||||||
|
#define SrcDir "."
|
||||||
|
#endif
|
||||||
|
#ifndef OutDir
|
||||||
|
#define OutDir "."
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define MyAppName "岩美酒库"
|
||||||
|
#define MyAppExe "jiu_client.exe"
|
||||||
|
#define MyAppPublisher "岩美"
|
||||||
|
|
||||||
|
[Setup]
|
||||||
|
AppId={{A3F5C1E2-9B47-4D8A-B6E0-2C1D4F8A9E33}
|
||||||
|
AppName={#MyAppName}
|
||||||
|
AppVersion={#AppVer}
|
||||||
|
AppPublisher={#MyAppPublisher}
|
||||||
|
DefaultDirName={autopf}\Jiu
|
||||||
|
DefaultGroupName={#MyAppName}
|
||||||
|
DisableProgramGroupPage=yes
|
||||||
|
OutputDir={#OutDir}
|
||||||
|
OutputBaseFilename=jiu-windows-x64-setup
|
||||||
|
Compression=lzma2
|
||||||
|
SolidCompression=yes
|
||||||
|
WizardStyle=modern
|
||||||
|
ArchitecturesAllowed=x64
|
||||||
|
ArchitecturesInstallIn64BitMode=x64
|
||||||
|
UninstallDisplayName={#MyAppName}
|
||||||
|
UninstallDisplayIcon={app}\{#MyAppExe}
|
||||||
|
|
||||||
|
[Languages]
|
||||||
|
Name: "chinesesimp"; MessagesFile: "compiler:Languages\ChineseSimplified.isl"
|
||||||
|
|
||||||
|
[Tasks]
|
||||||
|
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: checkedonce
|
||||||
|
|
||||||
|
[Files]
|
||||||
|
Source: "{#SrcDir}\*"; DestDir: "{app}"; Flags: recursesubdirs createallsubdirs ignoreversion
|
||||||
|
|
||||||
|
[Icons]
|
||||||
|
Name: "{group}\{#MyAppName}"; Filename: "{app}\{#MyAppExe}"
|
||||||
|
Name: "{group}\卸载 {#MyAppName}"; Filename: "{uninstallexe}"
|
||||||
|
Name: "{commondesktop}\{#MyAppName}"; Filename: "{app}\{#MyAppExe}"; Tasks: desktopicon
|
||||||
|
|
||||||
|
[Run]
|
||||||
|
Filename: "{app}\{#MyAppExe}"; Description: "{cm:LaunchProgram,{#MyAppName}}"; Flags: nowait postinstall skipifsilent
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# _env.sh — shared CI mirror env. `source` this from other scripts.
|
||||||
|
# Idempotent: only sets vars if not already provided by the environment.
|
||||||
|
|
||||||
|
export GOPROXY="${GOPROXY:-https://goproxy.cn,direct}"
|
||||||
|
export PUB_HOSTED_URL="${PUB_HOSTED_URL:-https://pub.flutter-io.cn}"
|
||||||
|
export FLUTTER_STORAGE_BASE_URL="${FLUTTER_STORAGE_BASE_URL:-https://storage.flutter-io.cn}"
|
||||||
|
|
||||||
|
# Ensure Homebrew tools are on PATH (macOS runners); harmless elsewhere.
|
||||||
|
case ":${PATH}:" in
|
||||||
|
*":/opt/homebrew/bin:"*) ;;
|
||||||
|
*) export PATH="/opt/homebrew/bin:${PATH}" ;;
|
||||||
|
esac
|
||||||
@@ -2,9 +2,8 @@
|
|||||||
# compile-macos.sh <tag> — build Flutter macOS desktop, package into dist/
|
# compile-macos.sh <tag> — build Flutter macOS desktop, package into dist/
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
export GOPROXY="${GOPROXY:-https://goproxy.cn,direct}"
|
# shellcheck source=scripts/ci/_env.sh
|
||||||
export PUB_HOSTED_URL="${PUB_HOSTED_URL:-https://pub.flutter-io.cn}"
|
. "$(dirname "$0")/_env.sh"
|
||||||
export FLUTTER_STORAGE_BASE_URL="${FLUTTER_STORAGE_BASE_URL:-https://storage.flutter-io.cn}"
|
|
||||||
|
|
||||||
TAG="$1"
|
TAG="$1"
|
||||||
VER="${TAG#v}"
|
VER="${TAG#v}"
|
||||||
|
|||||||
@@ -2,52 +2,73 @@
|
|||||||
# compile-windows.sh <tag> — build Flutter Windows desktop, package into dist/
|
# compile-windows.sh <tag> — build Flutter Windows desktop, package into dist/
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
export GOPROXY="${GOPROXY:-https://goproxy.cn,direct}"
|
# shellcheck source=scripts/ci/_env.sh
|
||||||
export PUB_HOSTED_URL="${PUB_HOSTED_URL:-https://pub.flutter-io.cn}"
|
. "$(dirname "$0")/_env.sh"
|
||||||
export FLUTTER_STORAGE_BASE_URL="${FLUTTER_STORAGE_BASE_URL:-https://storage.flutter-io.cn}"
|
|
||||||
|
|
||||||
TAG="$1"
|
TAG="$1"
|
||||||
VER="${TAG#v}"
|
VER="${TAG#v}"
|
||||||
|
|
||||||
echo "==> compile-windows: version=${VER}"
|
echo "==> compile-windows: version=${VER}"
|
||||||
|
|
||||||
# Sync Flutter pubspec version
|
# Sync Flutter pubspec version (done in the checkout, before copying out)
|
||||||
sed -i "s/^version:.*/version: ${VER}+1/" client/pubspec.yaml
|
sed -i "s/^version:.*/version: ${VER}+1/" client/pubspec.yaml
|
||||||
|
|
||||||
# Build Flutter Windows
|
# The Forgejo Windows runner checks out under
|
||||||
# Use subst to create a short path (W:) to avoid WOW64 redirection issue
|
# C:\Windows\System32\config\systemprofile\.cache\act\...\hostexecutor
|
||||||
# when workspace is under C:\Windows\System32\config\systemprofile
|
# Building there triggers WOW64 filesystem redirection (System32 -> SysWOW64)
|
||||||
WORKSPACE_WIN=$(cygpath -w "$(pwd)")
|
# which breaks CMake/Flutter native paths. So copy the Flutter project to a
|
||||||
echo "==> workspace: $WORKSPACE_WIN"
|
# clean short path OUTSIDE System32 and build there. This replaces the previous
|
||||||
cmd //c "subst W: \"${WORKSPACE_WIN}\"" || true
|
# `subst W:` trick, which was fragile due to cmd/MSYS quoting.
|
||||||
|
BUILD_ROOT="/c/jiu-build"
|
||||||
|
BUILD_CLIENT="${BUILD_ROOT}/client"
|
||||||
|
|
||||||
cd /w/client
|
echo "==> copying client/ to ${BUILD_CLIENT}"
|
||||||
|
rm -rf "$BUILD_ROOT"
|
||||||
|
mkdir -p "$BUILD_ROOT"
|
||||||
|
cp -r client "$BUILD_CLIENT"
|
||||||
|
|
||||||
|
# `cp -r` turns Flutter's plugin symlinks (windows/flutter/ephemeral/.plugin_symlinks/*)
|
||||||
|
# into real directories. flutter's createPluginSymlinks only cleans up *symlinks*, so it
|
||||||
|
# then fails to create a symlink over the copied real dir (errno 183 / PathExists).
|
||||||
|
# Drop all regenerable artifacts so the build below recreates them cleanly.
|
||||||
|
rm -rf "${BUILD_CLIENT}/windows/flutter/ephemeral" \
|
||||||
|
"${BUILD_CLIENT}/.dart_tool" \
|
||||||
|
"${BUILD_CLIENT}/build"
|
||||||
|
|
||||||
|
# Build (run from the clean path; pushd/popd avoids needing $() to save cwd)
|
||||||
|
pushd "$BUILD_CLIENT" > /dev/null
|
||||||
flutter create --platforms=windows . --project-name jiu_client
|
flutter create --platforms=windows . --project-name jiu_client
|
||||||
flutter build windows --release \
|
flutter build windows --release \
|
||||||
"--dart-define=BASE_URL=https://jiu.51yanmei.com" \
|
"--dart-define=BASE_URL=https://jiu.51yanmei.com" \
|
||||||
"--dart-define=PUBLIC_URL=https://jiu.51yanmei.com" \
|
"--dart-define=PUBLIC_URL=https://jiu.51yanmei.com" \
|
||||||
"--dart-define=APP_VERSION=${TAG}"
|
"--dart-define=APP_VERSION=${TAG}"
|
||||||
cd /w
|
popd > /dev/null
|
||||||
|
|
||||||
cmd //c "subst W: /d" || true
|
# Package the Release folder into a Windows installer with Inno Setup (ISCC).
|
||||||
|
# Inno Setup is installed by provision-windows.sh.
|
||||||
|
ISCC="/c/Program Files (x86)/Inno Setup 6/ISCC.exe"
|
||||||
|
if [ ! -f "$ISCC" ]; then
|
||||||
|
echo "ERROR: Inno Setup (ISCC) not found at '$ISCC'. Run provision-windows.sh first." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
# Package release folder into zip using Python (available on all platforms)
|
# Run ISCC entirely under the clean build root: 32-bit ISCC would hit WOW64
|
||||||
|
# redirection if it read the .iss / wrote output under the System32 workspace.
|
||||||
|
cp deploy/windows/jiu-installer.iss "${BUILD_ROOT}/jiu-installer.iss"
|
||||||
|
mkdir -p "${BUILD_ROOT}/dist"
|
||||||
|
echo "==> building installer with Inno Setup (version ${VER})"
|
||||||
|
"$ISCC" \
|
||||||
|
"/DAppVer=${VER}" \
|
||||||
|
"/DSrcDir=C:\\jiu-build\\client\\build\\windows\\x64\\runner\\Release" \
|
||||||
|
"/DOutDir=C:\\jiu-build\\dist" \
|
||||||
|
"C:\\jiu-build\\jiu-installer.iss"
|
||||||
|
|
||||||
|
# Copy the installer back to the workspace dist/ via PowerShell (64-bit, so it
|
||||||
|
# can write the System32 workspace path without WOW64 redirection).
|
||||||
mkdir -p dist
|
mkdir -p dist
|
||||||
python3 - <<'PYEOF'
|
echo "==> copying installer -> dist/jiu-windows-x64-setup.exe"
|
||||||
import zipfile, os
|
powershell -NoProfile -Command \
|
||||||
|
"Copy-Item 'C:\\jiu-build\\dist\\jiu-windows-x64-setup.exe' 'dist\\jiu-windows-x64-setup.exe' -Force"
|
||||||
src = os.path.join('W:\\', 'client', 'build', 'windows', 'x64', 'runner', 'Release') if os.path.exists('W:\\') else os.path.join('client', 'build', 'windows', 'x64', 'runner', 'Release')
|
|
||||||
dst = os.path.join('dist', 'jiu-windows-x64.zip')
|
|
||||||
|
|
||||||
with zipfile.ZipFile(dst, 'w', zipfile.ZIP_DEFLATED) as zf:
|
|
||||||
for root, dirs, files in os.walk(src):
|
|
||||||
for fname in files:
|
|
||||||
fp = os.path.join(root, fname)
|
|
||||||
zf.write(fp, os.path.relpath(fp, src))
|
|
||||||
|
|
||||||
size = os.path.getsize(dst)
|
|
||||||
print(f'Packaged {dst} ({size // 1024 // 1024} MB)')
|
|
||||||
PYEOF
|
|
||||||
|
|
||||||
echo "==> compile-windows: done — dist/ contents:"
|
echo "==> compile-windows: done — dist/ contents:"
|
||||||
ls -lh dist/
|
ls -lh dist/
|
||||||
|
|||||||
@@ -2,10 +2,8 @@
|
|||||||
# compile.sh <tag> — build backend + Flutter web, package into dist/
|
# compile.sh <tag> — build backend + Flutter web, package into dist/
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
export PATH="/opt/homebrew/bin:$PATH"
|
# shellcheck source=scripts/ci/_env.sh
|
||||||
export GOPROXY="${GOPROXY:-https://goproxy.cn,direct}"
|
. "$(dirname "$0")/_env.sh"
|
||||||
export PUB_HOSTED_URL="${PUB_HOSTED_URL:-https://pub.flutter-io.cn}"
|
|
||||||
export FLUTTER_STORAGE_BASE_URL="${FLUTTER_STORAGE_BASE_URL:-https://storage.flutter-io.cn}"
|
|
||||||
|
|
||||||
TAG="$1"
|
TAG="$1"
|
||||||
VER="${TAG#v}"
|
VER="${TAG#v}"
|
||||||
|
|||||||
+16
-3
@@ -90,6 +90,11 @@ rsync -avz --delete -e "ssh -i ~/.ssh/ec2_deploy.pem -o StrictHostKeyChecking=no
|
|||||||
rsync -avz --delete -e "ssh -i ~/.ssh/ec2_deploy.pem -o StrictHostKeyChecking=no" \
|
rsync -avz --delete -e "ssh -i ~/.ssh/ec2_deploy.pem -o StrictHostKeyChecking=no" \
|
||||||
/tmp/jiu-marketing-new/ "${EC2_USER}@${EC2_HOST}:/tmp/jiu-marketing-new/"
|
/tmp/jiu-marketing-new/ "${EC2_USER}@${EC2_HOST}:/tmp/jiu-marketing-new/"
|
||||||
|
|
||||||
|
# Upload desktop client installers (served from /downloads/ by nginx).
|
||||||
|
# Guarded: may be absent in a partial manual deploy.
|
||||||
|
[ -f dist/jiu-windows-x64-setup.exe ] && ${SCP} dist/jiu-windows-x64-setup.exe "${EC2_USER}@${EC2_HOST}:/tmp/jiu-windows-x64-setup.exe" || true
|
||||||
|
[ -f dist/jiu-macos-x64.zip ] && ${SCP} dist/jiu-macos-x64.zip "${EC2_USER}@${EC2_HOST}:/tmp/jiu-macos-x64.zip" || true
|
||||||
|
|
||||||
echo "==> deploy: running remote deploy"
|
echo "==> deploy: running remote deploy"
|
||||||
|
|
||||||
${SSH} "${EC2_USER}@${EC2_HOST}" << 'ENDSSH'
|
${SSH} "${EC2_USER}@${EC2_HOST}" << 'ENDSSH'
|
||||||
@@ -126,9 +131,17 @@ mkdir -p /opt/jiu/marketing
|
|||||||
rsync -a --delete /tmp/jiu-marketing-new/ /opt/jiu/marketing/
|
rsync -a --delete /tmp/jiu-marketing-new/ /opt/jiu/marketing/
|
||||||
rm -rf /tmp/jiu-marketing-new
|
rm -rf /tmp/jiu-marketing-new
|
||||||
|
|
||||||
# Update nginx config and reload
|
# Publish desktop client installers to the nginx-served downloads dir
|
||||||
sudo cp /tmp/nginx-jiu.conf /etc/nginx/conf.d/jiu.conf
|
mkdir -p /opt/jiu/downloads
|
||||||
sudo nginx -t && sudo nginx -s reload
|
[ -f /tmp/jiu-windows-x64-setup.exe ] && mv -f /tmp/jiu-windows-x64-setup.exe /opt/jiu/downloads/ || true
|
||||||
|
[ -f /tmp/jiu-macos-x64.zip ] && mv -f /tmp/jiu-macos-x64.zip /opt/jiu/downloads/ || true
|
||||||
|
|
||||||
|
# Update jiu nginx config in the pangolin-edge reverse proxy.
|
||||||
|
# nginx now runs inside the `pangolin-edge` container (host networking), not on
|
||||||
|
# the host. Its /etc/nginx/conf.d is bind-mounted from the host dir below, so we
|
||||||
|
# write the config there and reload nginx *inside the container*.
|
||||||
|
cp /tmp/nginx-jiu.conf /home/ec2-user/pangolin/edge/conf.d/jiu.conf
|
||||||
|
docker exec pangolin-edge nginx -t && docker exec pangolin-edge nginx -s reload
|
||||||
|
|
||||||
echo "Deploy complete!"
|
echo "Deploy complete!"
|
||||||
ENDSSH
|
ENDSSH
|
||||||
|
|||||||
@@ -0,0 +1,62 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# provision-mac.sh — idempotent provisioning for the macOS host runner.
|
||||||
|
#
|
||||||
|
# Pre-warms everything the build jobs (compile.sh / compile-macos.sh) would
|
||||||
|
# otherwise download at runtime: Flutter macOS+web engine artifacts, pub
|
||||||
|
# packages, Go modules, npm deps. Safe to run on every pipeline run — it
|
||||||
|
# short-circuits via a stamp file keyed to the installed Flutter version, so
|
||||||
|
# once provisioned it returns in milliseconds and downloads nothing.
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(dirname "$0")"
|
||||||
|
# shellcheck source=scripts/ci/_env.sh
|
||||||
|
. "${SCRIPT_DIR}/_env.sh"
|
||||||
|
|
||||||
|
STAMP_DIR="${HOME}/.cache/jiu-ci"
|
||||||
|
STAMP="${STAMP_DIR}/provisioned-mac"
|
||||||
|
CUR="${STAMP_DIR}/.flutter-version-mac.cur"
|
||||||
|
mkdir -p "$STAMP_DIR"
|
||||||
|
|
||||||
|
# --- detection: skip if already provisioned for this Flutter version ---
|
||||||
|
if ! command -v flutter >/dev/null 2>&1; then
|
||||||
|
echo "ERROR: flutter not found on PATH. Install Flutter on this runner first." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
flutter --version --machine > "$CUR" 2>/dev/null || flutter --version > "$CUR" 2>&1 || true
|
||||||
|
|
||||||
|
if [ -s "$STAMP" ] && cmp -s "$STAMP" "$CUR"; then
|
||||||
|
echo "==> provision-mac: already provisioned (Flutter unchanged), skipping."
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "==> provision-mac: not provisioned (or Flutter changed) — running."
|
||||||
|
|
||||||
|
# --- toolchain presence (do not auto-install system-level tools) ---
|
||||||
|
for tool in go node npm; do
|
||||||
|
if ! command -v "$tool" >/dev/null 2>&1; then
|
||||||
|
echo "ERROR: '$tool' not found on PATH. Install it on this runner first." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# --- warm Flutter platform engines (the macOS SDK download seen in CI) ---
|
||||||
|
echo "==> precache Flutter engines (macos, web)"
|
||||||
|
flutter precache --macos --web --universal
|
||||||
|
|
||||||
|
# --- warm dependency caches ---
|
||||||
|
echo "==> flutter pub get (client)"
|
||||||
|
(cd "${SCRIPT_DIR}/../../client" && flutter pub get)
|
||||||
|
|
||||||
|
echo "==> go mod download (backend)"
|
||||||
|
(cd "${SCRIPT_DIR}/../../backend" && go mod download)
|
||||||
|
|
||||||
|
echo "==> npm ci (web)"
|
||||||
|
(cd "${SCRIPT_DIR}/../../web" && npm ci --prefer-offline)
|
||||||
|
|
||||||
|
# --- mark provisioned ---
|
||||||
|
cp "$CUR" "$STAMP"
|
||||||
|
echo "==> provision-mac: done."
|
||||||
|
echo "--- versions ---"
|
||||||
|
flutter --version | head -1
|
||||||
|
go version
|
||||||
|
node --version
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# provision-windows.sh — idempotent provisioning for the Windows host runner.
|
||||||
|
#
|
||||||
|
# Pre-warms what compile-windows.sh would download at runtime: Flutter Windows
|
||||||
|
# engine artifacts, pub packages, and the Inno Setup compiler (ISCC) used to
|
||||||
|
# build the installer. The Flutter part short-circuits via a stamp keyed to the
|
||||||
|
# installed Flutter version; Inno Setup is ensured on every run (cheap when
|
||||||
|
# already present) so it self-heals independently of the Flutter stamp.
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(dirname "$0")"
|
||||||
|
# shellcheck source=scripts/ci/_env.sh
|
||||||
|
. "${SCRIPT_DIR}/_env.sh"
|
||||||
|
|
||||||
|
STAMP_DIR="${HOME}/.cache/jiu-ci"
|
||||||
|
STAMP="${STAMP_DIR}/provisioned-windows"
|
||||||
|
CUR="${STAMP_DIR}/.flutter-version-win.cur"
|
||||||
|
mkdir -p "$STAMP_DIR"
|
||||||
|
|
||||||
|
# --- ensure Inno Setup (ISCC) for building the installer (always checked) ---
|
||||||
|
ISCC="/c/Program Files (x86)/Inno Setup 6/ISCC.exe"
|
||||||
|
if [ ! -f "$ISCC" ]; then
|
||||||
|
echo "==> installing Inno Setup 6 (silent)"
|
||||||
|
# Canonical "latest stable" entry point (redirects to the GitHub release asset).
|
||||||
|
INNO_URL="https://jrsoftware.org/download.php/is.exe"
|
||||||
|
powershell -NoProfile -Command \
|
||||||
|
"Invoke-WebRequest -Uri '${INNO_URL}' -OutFile \"\$env:TEMP\\innosetup.exe\""
|
||||||
|
powershell -NoProfile -Command \
|
||||||
|
"Start-Process -Wait -FilePath \"\$env:TEMP\\innosetup.exe\" -ArgumentList '/VERYSILENT','/SUPPRESSMSGBOXES','/NORESTART','/SP-'"
|
||||||
|
if [ ! -f "$ISCC" ]; then
|
||||||
|
echo "ERROR: Inno Setup install failed — ISCC not found at '$ISCC'." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo "==> Inno Setup installed."
|
||||||
|
fi
|
||||||
|
|
||||||
|
# --- detection (Flutter) ---
|
||||||
|
if ! command -v flutter >/dev/null 2>&1; then
|
||||||
|
echo "ERROR: flutter not found on PATH. Install Flutter on this runner first." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
flutter --version --machine > "$CUR" 2>/dev/null || flutter --version > "$CUR" 2>&1 || true
|
||||||
|
|
||||||
|
if [ -s "$STAMP" ] && cmp -s "$STAMP" "$CUR"; then
|
||||||
|
echo "==> provision-windows: already provisioned (Flutter unchanged), skipping."
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "==> provision-windows: not provisioned (or Flutter changed) — running."
|
||||||
|
|
||||||
|
# --- warm Flutter Windows engine + pub deps ---
|
||||||
|
echo "==> precache Flutter engine (windows)"
|
||||||
|
flutter precache --windows
|
||||||
|
|
||||||
|
echo "==> flutter pub get (client)"
|
||||||
|
(cd "${SCRIPT_DIR}/../../client" && flutter pub get)
|
||||||
|
|
||||||
|
# --- mark provisioned ---
|
||||||
|
cp "$CUR" "$STAMP"
|
||||||
|
echo "==> provision-windows: done."
|
||||||
|
flutter --version | head -1
|
||||||
@@ -44,9 +44,13 @@ notes = sys.argv[2]
|
|||||||
tag = sys.argv[3]
|
tag = sys.argv[3]
|
||||||
furl = sys.argv[4].rstrip('/')
|
furl = sys.argv[4].rstrip('/')
|
||||||
repo = sys.argv[5]
|
repo = sys.argv[5]
|
||||||
base = f"{furl}/{repo}/releases/download/{tag}"
|
# Public download URLs are served by jiu.51yanmei.com (same-origin HTTPS via the
|
||||||
|
# pangolin nginx /downloads/ location), NOT the LAN-only HTTP Forgejo instance —
|
||||||
|
# otherwise the HTTPS download page hands the browser an http://192.168.x URL and
|
||||||
|
# Chrome blocks it as insecure / it's unreachable from the public internet.
|
||||||
|
base = "https://jiu.51yanmei.com/downloads"
|
||||||
mac_url = f"{base}/jiu-macos-x64.zip"
|
mac_url = f"{base}/jiu-macos-x64.zip"
|
||||||
win_url = f"{base}/jiu-windows-x64.zip"
|
win_url = f"{base}/jiu-windows-x64-setup.exe"
|
||||||
|
|
||||||
lines = []
|
lines = []
|
||||||
with open('backend/config/version.yaml') as f:
|
with open('backend/config/version.yaml') as f:
|
||||||
@@ -128,6 +132,6 @@ upload_asset dist/web.tar.gz
|
|||||||
upload_asset dist/marketing.tar.gz
|
upload_asset dist/marketing.tar.gz
|
||||||
upload_asset dist/configs.tar.gz
|
upload_asset dist/configs.tar.gz
|
||||||
upload_asset dist/jiu-macos-x64.zip
|
upload_asset dist/jiu-macos-x64.zip
|
||||||
upload_asset dist/jiu-windows-x64.zip
|
upload_asset dist/jiu-windows-x64-setup.exe
|
||||||
|
|
||||||
echo "==> release: done — Release ${TAG} created"
|
echo "==> release: done — Release ${TAG} created"
|
||||||
|
|||||||
Reference in New Issue
Block a user