Skip to content

Commit fdc9a4e

Browse files
committed
ci: add nightly build workflow and OpenSpec updates
1 parent 4795c3c commit fdc9a4e

22 files changed

Lines changed: 1172 additions & 21 deletions

File tree

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
# LinaPro nightly multi-platform Docker image publishing workflow.
2+
# GitHub cron uses UTC. 16:00 UTC is 00:00 Asia/Shanghai.
3+
name: Nightly Build
4+
5+
on:
6+
schedule:
7+
- cron: "0 16 * * *"
8+
9+
workflow_dispatch:
10+
11+
permissions:
12+
contents: read
13+
packages: write
14+
15+
concurrency:
16+
group: "${{ github.workflow }} @ nightly"
17+
cancel-in-progress: false
18+
19+
env:
20+
TZ: "Asia/Shanghai"
21+
IMAGE_NAME: "linapro"
22+
PLATFORMS: "linux/amd64,linux/arm64"
23+
24+
jobs:
25+
nightly-image:
26+
name: Build and publish nightly image
27+
runs-on: ubuntu-latest
28+
timeout-minutes: 90
29+
30+
steps:
31+
- name: Checkout Repository
32+
uses: actions/checkout@v5
33+
34+
- name: Setup Go
35+
uses: actions/setup-go@v5
36+
with:
37+
go-version: "1.25"
38+
cache-dependency-path: "**/go.sum"
39+
40+
- name: Setup pnpm
41+
uses: pnpm/action-setup@v4
42+
with:
43+
version: "10.30.3"
44+
run_install: false
45+
46+
- name: Setup Node
47+
uses: actions/setup-node@v5
48+
with:
49+
node-version-file: "apps/lina-vben/.node-version"
50+
cache: "pnpm"
51+
cache-dependency-path: "apps/lina-vben/pnpm-lock.yaml"
52+
53+
- name: Install Frontend Dependencies
54+
working-directory: apps/lina-vben
55+
run: pnpm install --frozen-lockfile
56+
57+
- name: Setup QEMU
58+
uses: docker/setup-qemu-action@v3
59+
60+
- name: Setup Docker Buildx
61+
uses: docker/setup-buildx-action@v3
62+
63+
- name: Login to GHCR
64+
uses: docker/login-action@v3
65+
with:
66+
registry: ghcr.io
67+
username: ${{ github.actor }}
68+
password: ${{ secrets.GITHUB_TOKEN }}
69+
70+
- name: Prepare Image Metadata
71+
id: image
72+
run: |
73+
owner="$(printf '%s' "${GITHUB_REPOSITORY_OWNER}" | tr '[:upper:]' '[:lower:]')"
74+
image_name="$(printf '%s' "${IMAGE_NAME}" | tr '[:upper:]' '[:lower:]')"
75+
registry="ghcr.io/${owner}"
76+
date_tag="nightly-$(date +'%Y%m%d')"
77+
image_ref="${registry}/${image_name}"
78+
79+
{
80+
echo "registry=${registry}"
81+
echo "image_name=${image_name}"
82+
echo "date_tag=${date_tag}"
83+
echo "image_ref=${image_ref}"
84+
} >> "${GITHUB_OUTPUT}"
85+
86+
echo "Publishing ${image_ref}:${date_tag} for ${PLATFORMS}"
87+
88+
- name: Build and Push Multi-Platform Image
89+
run: |
90+
make image \
91+
config=".github/workflows/nightly-build/config.yaml" \
92+
platforms="${PLATFORMS}" \
93+
registry="${{ steps.image.outputs.registry }}" \
94+
image="${{ steps.image.outputs.image_name }}" \
95+
tag="${{ steps.image.outputs.date_tag }}" \
96+
push=1
97+
98+
- name: Publish Floating Nightly Tag
99+
run: |
100+
docker buildx imagetools create \
101+
--tag "${{ steps.image.outputs.image_ref }}:nightly" \
102+
"${{ steps.image.outputs.image_ref }}:${{ steps.image.outputs.date_tag }}"
103+
104+
- name: Inspect Published Manifest
105+
run: |
106+
docker buildx imagetools inspect "${{ steps.image.outputs.image_ref }}:${{ steps.image.outputs.date_tag }}"
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
ARG BASE_IMAGE=alpine:3.22
2+
FROM ${BASE_IMAGE}
3+
ARG TARGETOS
4+
ARG TARGETARCH
5+
6+
###############################################################################
7+
# INSTALLATION
8+
###############################################################################
9+
10+
ENV WORKDIR=/app
11+
ENV TZ=Asia/Shanghai
12+
13+
RUN apk add --no-cache ca-certificates tzdata
14+
15+
COPY temp/image/${TARGETOS}/${TARGETARCH}/lina $WORKDIR/lina
16+
COPY .github/workflows/nightly-build/config.runtime.yaml $WORKDIR/config.yaml
17+
18+
###############################################################################
19+
# START
20+
###############################################################################
21+
WORKDIR $WORKDIR
22+
EXPOSE 8080
23+
ENTRYPOINT ["./lina"]
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
# HTTP server configuration
2+
# HTTP 服务配置
3+
server:
4+
address: ":8080"
5+
dumpRouterMap: false
6+
extensions:
7+
apiDocPath: "/api.json"
8+
9+
# Logging configuration
10+
# 日志配置
11+
logger:
12+
path: ""
13+
file: "{Y-m-d}.log"
14+
level: "all"
15+
stdout: true
16+
extensions:
17+
structured: false
18+
traceIDEnabled: false
19+
20+
# Database configuration
21+
# 数据库配置
22+
database:
23+
default:
24+
link: "sqlite::@file(./data/sqlite/linapro.db)"
25+
debug: false
26+
27+
# JWT configuration
28+
# JWT 配置
29+
jwt:
30+
secret: "lina-jwt-secret-key-change-in-production"
31+
expire: 24h
32+
33+
# Online session configuration
34+
# 在线会话配置
35+
session:
36+
timeout: 24h
37+
cleanupInterval: 5m
38+
39+
# Service monitoring configuration
40+
# 服务监控配置
41+
monitor:
42+
interval: 1m
43+
44+
# Health probe configuration
45+
# 健康探针配置
46+
health:
47+
timeout: 5s
48+
49+
# Graceful shutdown configuration
50+
# 优雅关停配置
51+
shutdown:
52+
timeout: 30s
53+
54+
# Scheduler configuration
55+
# 调度器配置
56+
scheduler:
57+
defaultTimezone: "UTC"
58+
59+
# Internationalization configuration
60+
# 国际化配置
61+
i18n:
62+
default: zh-CN
63+
enabled: true
64+
locales:
65+
- locale: en-US
66+
nativeName: English
67+
- locale: zh-CN
68+
nativeName: 简体中文
69+
- locale: zh-TW
70+
nativeName: 繁體中文
71+
72+
# Cluster deployment configuration
73+
# SQLite forces cluster mode off at startup.
74+
# SQLite 会在启动期强制关闭集群模式。
75+
cluster:
76+
enabled: false
77+
election:
78+
lease: 30s
79+
renewInterval: 10s
80+
81+
# Upload configuration
82+
# 上传配置
83+
upload:
84+
path: "data/upload"
85+
maxSize: 20
86+
87+
# Plugin configuration
88+
# 插件配置
89+
plugin:
90+
dynamic:
91+
storagePath: "data/wasm"
92+
autoEnable: []
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# Repository-level development and delivery tool configuration.
2+
# 仓库级开发与交付工具配置。
3+
4+
build:
5+
# Target platforms for host binaries and Docker images.
6+
# Each item uses goos/goarch form, or "auto" for the current system platform.
7+
# 宿主二进制与 Docker 镜像的目标平台列表。
8+
# 每一项使用 goos/goarch 格式,或使用 "auto" 表示当前系统平台。
9+
platforms:
10+
- "linux/amd64"
11+
- "linux/arm64"
12+
# Whether to enable CGO when building the host binary.
13+
# 构建宿主二进制时是否启用 CGO。
14+
cgoEnabled: false
15+
# Standard build output path, relative to the repository root.
16+
# 标准构建产物路径,相对于仓库根目录。
17+
outputDir: "temp/output"
18+
# Host binary filename generated by make build.
19+
# make build 生成的宿主二进制文件名。
20+
binaryName: "lina"
21+
22+
23+
image:
24+
# Default image repository name. A configured registry is prepended at build time.
25+
# 默认镜像仓库名。构建时会在前面拼接已配置的远端仓库前缀。
26+
name: "linapro"
27+
# Optional default tag. Leave empty to derive one from git.
28+
# 可选默认镜像标签。留空时会根据 git 信息自动推导。
29+
tag: ""
30+
# Optional remote registry prefix, for example "ghcr.io/linaproai".
31+
# 可选远端仓库前缀,例如 "ghcr.io/linaproai"。
32+
registry: ""
33+
# Default push behavior. Command-line push=1 overrides this for one invocation.
34+
# 默认是否推送镜像。命令行 push=1 可仅覆盖本次执行。
35+
push: false
36+
# Runtime base image used by hack/docker/Dockerfile.
37+
# hack/docker/Dockerfile 使用的运行时基础镜像。
38+
baseImage: "alpine:3.22"
39+
# Dockerfile path, relative to the repository root.
40+
# Dockerfile 路径,相对于仓库根目录。
41+
dockerfile: ".github/workflows/nightly-build/Dockerfile"

README.md

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -164,12 +164,4 @@ Plugins are the primary extension point in `LinaPro`. Each plugin is a self-cont
164164
| Database | `MySQL` / optional `SQLite` | `MySQL 8.0+` is the primary data store. `SQLite` can be used for demo or local test mode without MySQL; it is single-node only and not for production. |
165165
| Plugin Runtime | `WebAssembly` | `tetratelabs/wazero`, powering WASM dynamic plugins |
166166

167-
# Release Builds
168167

169-
`make build` supports cross-compiling the host binary, for example `make build platforms=linux/arm64`. `make image` supports multi-platform Docker publishing through `Docker buildx`:
170-
171-
```bash
172-
make image platforms=linux/amd64,linux/arm64 registry=ghcr.io/linaproai tag=v0.6.0 push=1
173-
```
174-
175-
Multi-platform image builds require `push=1` so the remote image manifest is published.

README.zh-CN.md

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -165,12 +165,4 @@ graph TB
165165
| 数据库 | `MySQL` / 可选 `SQLite` | `MySQL 8.0+` 为主数据存储;`SQLite` 可用于无需 MySQL 的演示或本地测试模式,仅支持单节点,不适用于生产 |
166166
| 插件运行时 | `WebAssembly` | `tetratelabs/wazero`,支持`WASM`动态插件 |
167167

168-
# 发布构建
169168

170-
`make build`支持交叉编译宿主二进制,例如`make build platforms=linux/arm64``make image`支持通过`Docker buildx`发布多平台镜像:
171-
172-
```bash
173-
make image platforms=linux/amd64,linux/arm64 registry=ghcr.io/linaproai tag=v0.6.0 push=1
174-
```
175-
176-
多平台镜像构建必须启用`push=1`,以便发布远端镜像 manifest。

hack/makefiles/build.mk

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ endif
2222
ifneq ($(origin binary_name), undefined)
2323
BUILD_CONFIG_ARGS += --binary-name=$(binary_name)
2424
endif
25+
ifneq ($(origin config), undefined)
26+
BUILD_CONFIG_ARGS += --config=$(config)
27+
endif
2528

2629
# Helper macro that optionally hides noisy build command output.
2730
# 构建命令辅助宏,可按需隐藏详细输出。
@@ -43,7 +46,7 @@ endef
4346

4447
# Build frontend assets, packed manifests, dynamic plugins, and the host binary.
4548
# 构建前端资源、嵌入 manifest、动态插件和宿主后端二进制。
46-
## build: Build frontend assets, host manifest assets, runtime wasm plugins, and host binaries using hack/config.yaml build settings; supports platforms=linux/amd64,linux/arm64, verbose=1, or v=1
49+
## build: Build frontend assets, host manifest assets, runtime wasm plugins, and host binaries using hack/config.yaml or config=<path>; supports platforms=linux/amd64,linux/arm64
4750
.PHONY: build
4851
build:
4952
@set -e; \

hack/makefiles/image.mk

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ endif
3333
ifneq ($(origin base_image), undefined)
3434
IMAGE_BUILDER_ARGS += --base-image=$(base_image)
3535
endif
36+
ifneq ($(origin config), undefined)
37+
IMAGE_BUILDER_ARGS += --config=$(config)
38+
endif
3639
ifneq ($(origin verbose), undefined)
3740
IMAGE_BUILDER_ARGS += --verbose=$(verbose)
3841
endif
@@ -42,11 +45,11 @@ endif
4245

4346
# Build the production Docker image from the standard make build output.
4447
# 基于标准 make build 产物构建生产 Docker 镜像。
45-
## image: Build the production Docker image from make build output and hack/config.yaml; supports tag=v0.6.0 registry=ghcr.io/linaproai push=1 platforms=linux/amd64,linux/arm64
48+
## image: Build the production Docker image from make build output and hack/config.yaml or config=<path>; supports tag=v0.6.0 registry=ghcr.io/linaproai push=1 platforms=linux/amd64,linux/arm64
4649
.PHONY: image
4750
image:
4851
@go run ./hack/tools/image-builder --preflight $(IMAGE_BUILDER_ARGS)
49-
@$(MAKE) build $(if $(platforms),platforms=$(platforms),) $(if $(cgo_enabled),cgo_enabled=$(cgo_enabled),) $(if $(output_dir),output_dir=$(output_dir),) $(if $(binary_name),binary_name=$(binary_name),) $(if $(verbose),verbose=$(verbose),) $(if $(v),v=$(v),)
52+
@$(MAKE) build $(if $(config),config=$(config),) $(if $(platforms),platforms=$(platforms),) $(if $(cgo_enabled),cgo_enabled=$(cgo_enabled),) $(if $(output_dir),output_dir=$(output_dir),) $(if $(binary_name),binary_name=$(binary_name),) $(if $(verbose),verbose=$(verbose),) $(if $(v),v=$(v),)
5053
@go run ./hack/tools/image-builder $(IMAGE_BUILDER_ARGS)
5154

5255
# Prepare image build artifacts without invoking Docker build.

hack/tools/image-builder/README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ make image tag=v0.6.0
1212
make image tag=v0.6.0 registry=ghcr.io/linaproai push=1
1313
make image platforms=linux/amd64
1414
make image platforms=linux/amd64,linux/arm64 registry=ghcr.io/linaproai tag=v0.6.0 push=1
15+
make image config=.github/workflows/nightly-build/config.yaml
1516
```
1617

1718
Direct tool invocation:
@@ -49,7 +50,7 @@ Image metadata defaults are read from `hack/config.yaml` under the `image` secti
4950
| `baseImage` | Runtime base image passed to the Dockerfile. |
5051
| `dockerfile` | Repository-relative Dockerfile path. Defaults to `hack/docker/Dockerfile`. |
5152

52-
Command-line flags override the config file for one invocation. `LINAPRO_IMAGE_REGISTRY` can also provide the registry prefix when neither the config nor `registry=...` is set.
53+
Command-line flags override the config file for one invocation. Use `config=<path>` on `make build` or `make image` to select a repository-level image-builder config file instead of `hack/config.yaml`. `LINAPRO_IMAGE_REGISTRY` can also provide the registry prefix when neither the config nor `registry=...` is set.
5354

5455
Repository structure paths such as `apps/lina-core`, `apps/lina-vben`, `apps/lina-plugins`, embedded public assets, packed manifest assets, and the `build-wasm` tool path are project conventions and are intentionally not exposed in `hack/config.yaml`.
5556

@@ -61,5 +62,6 @@ Repository structure paths such as `apps/lina-core`, `apps/lina-vben`, `apps/lin
6162
- `make build` compiles the host binary for the configured target platform.
6263
- `make build platforms=linux/amd64,linux/arm64` writes host binaries into `temp/output/linux_amd64/lina` and `temp/output/linux_arm64/lina`.
6364
- `make image` stages the standard host binary into the Docker build context instead of rebuilding it.
65+
- `make image config=<path>` uses the given image-builder config file instead of `hack/config.yaml`.
6466
- Single-platform Docker builds use `docker build`; multi-platform Docker builds use `docker buildx build --push`.
6567
- Docker builds `<registry-prefix>/<name>:<tag>` and only pushes when `push=true`. Multi-platform builds require `push=true` so the remote manifest is published.

hack/tools/image-builder/README.zh_CN.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ make image tag=v0.6.0
1212
make image tag=v0.6.0 registry=ghcr.io/linaproai push=1
1313
make image platforms=linux/amd64
1414
make image platforms=linux/amd64,linux/arm64 registry=ghcr.io/linaproai tag=v0.6.0 push=1
15+
make image config=.github/workflows/nightly-build/config.yaml
1516
```
1617

1718
也可以直接调用工具:
@@ -49,7 +50,7 @@ make image platforms=linux/amd64,linux/arm64 registry=ghcr.io/linaproai tag=v0.6
4950
| `baseImage` | 传递给`Dockerfile`的运行时基础镜像。 |
5051
| `dockerfile` | 相对于仓库根目录的`Dockerfile`路径,默认是`hack/docker/Dockerfile`|
5152

52-
命令行参数会覆盖本次调用的配置文件默认值。未通过配置或`registry=...`设置远端仓库时,也可以使用`LINAPRO_IMAGE_REGISTRY`提供仓库前缀。
53+
命令行参数会覆盖本次调用的配置文件默认值。`make build``make image`可使用`config=<path>`选择仓库级 image-builder 配置文件而不是`hack/config.yaml`未通过配置或`registry=...`设置远端仓库时,也可以使用`LINAPRO_IMAGE_REGISTRY`提供仓库前缀。
5354

5455
`apps/lina-core``apps/lina-vben``apps/lina-plugins`、前端嵌入资源、宿主`manifest`嵌入资源以及`build-wasm`工具路径属于项目结构约定,因此不会暴露到`hack/config.yaml`中。
5556

@@ -61,5 +62,6 @@ make image platforms=linux/amd64,linux/arm64 registry=ghcr.io/linaproai tag=v0.6
6162
- `make build`会按配置的目标平台编译宿主二进制。
6263
- `make build platforms=linux/amd64,linux/arm64`会分别写入`temp/output/linux_amd64/lina``temp/output/linux_arm64/lina`
6364
- `make image`会把标准宿主二进制 staged 到`Docker`构建上下文,而不是重新构建。
65+
- `make image config=<path>`会使用指定的 image-builder 配置文件而不是`hack/config.yaml`
6466
- 单平台镜像使用`docker build`,多平台镜像使用`docker buildx build --push`
6567
- `Docker`会构建`<registry-prefix>/<name>:<tag>`,只有`push=true`时才推送。多平台构建必须启用`push=true`,以便发布远端 manifest。

0 commit comments

Comments
 (0)