diff --git a/.dockerignore b/.dockerignore index a29e81754..95f00e403 100644 --- a/.dockerignore +++ b/.dockerignore @@ -7,8 +7,7 @@ build/*.sh build/*.bat scripts -docker -kubernetes +deployment cmake-build-debug test examples diff --git a/build/README.md b/build/README.md index 2a528a67f..5345e85ef 100755 --- a/build/README.md +++ b/build/README.md @@ -1,39 +1,61 @@ -# Binary +# Runtime files -Build artifacts are written to `/bin`. Use separate -build directories for Release, Debug and sanitizer builds so their archives, -plugins and executables cannot overwrite each other: +[简体中文](README_CN.md) + +Build artifacts belong to `/bin`. Keep Release, Debug and +sanitizer builds in separate directories. Stage an application's executable and +plugins from the same build into a runtime directory containing `bin/`, `conf/` +and, when required, `resource/`. This source directory contains example +configuration, resources and tools; generated binaries are not checked in. + +## Run one application + +The shell and Windows helpers share one interface: + +```text +run.sh [runtime-directory] +run.bat [runtime-directory] +``` + +The default runtime directory is the script's directory. An explicit runtime path +is relative to the caller's working directory. The helper selects `bin/app` +(`app.exe` on Windows) for Release or `bin/app_d` (`app_d.exe`) for Debug, reads +`conf/.app.conf` and `conf/log.conf`, and runs in the foreground. The name +also becomes the application's `--name` value. Use the executable directly for +TOML manifests, a different process name or other launcher flags. + +After preparing the [Sample1 runtime](../docs/get-started/quick-start.md), run from +the repository root: ```sh -cmake -S . -B out/release -DCMAKE_BUILD_TYPE=Release -cmake --build out/release --parallel 2 +sh build/run.sh Release sample1 1.0.1.1 run/sample1 ``` -This build produces `out/release/bin/app` (`app.exe` on Windows) and the enabled -plugins in the same directory. `cmake -S . -B build` retains the `build/bin` -location. The Docker build copies its artifacts from `cmake-build/bin`. - -When staging a server, copy the chosen build's artifacts into the runtime -directory's `bin/` alongside its configuration and resources. The scripts below -use this runtime layout; they do not select a CMake build directory. - -This folder is the runtime folder, include - -- bin -- binlog -- bus_conf -- plugin_conf -- resource -- tools - -## Batch/shell - -| name | descriptor | -| -------- | ------------------------------------- | -| rund.bat | run debug version in Windows | -| run.bat | run release version in Windows | -| kill.bat | kill debug & release version in Linux | -| | | -| run.sh | run release version in Linux | -| rund.sh | run debug version in Linux | -| kill.sh | kill debug & release version in Linux | +On Windows, use `build\run.bat Release sample1 1.0.1.1 run\sample1`. +Check the application's initialization log before using it; the helper's path +checks do not validate plugins, business configuration or readiness. + +## Stop one application + +Prefer Ctrl+C on macOS/Linux or `exit` in the Windows application console. +For a process whose PID has been confirmed, `kill.sh ` requests `SIGTERM`; +`kill.bat ` forcibly terminates that PID. Both helpers reject other executable +names and require exactly one explicit PID. Recheck the PID's executable and +command line immediately before use; a PID can be reused after a process exits. +There is no process-name wildcard or machine-wide stop command. + +## Migrate old helper commands + +- Replace `rund.sh` / `rund.bat` with `run.sh Debug ...` / `run.bat Debug ...`. +- Replace `sample1.sh`, `mysql_sample.sh` and `sample5http_test.sh` with + `run.sh Debug `, using `sample1`, `mysql_sample` or `sample5`. +- The old no-argument five-service launch sequence used missing `plugin_conf/` + paths and inconsistent Release/Debug Bus IDs. Supply each application's name + and Bus ID explicitly, and arrange service startup separately for the target + environment. The helper no longer daemonizes applications. +- Replace `vc_clear.bat` with `cmake --build --target clean` + to clean a selected build directory. +- Container recipes and cluster examples now live under [deployment/](../deployment/README.md). + +The byte-preserved historical articles under `docs/site/legacy-source/` still show +their original `bin/rund.*` commands. Use the current commands above instead. diff --git a/build/README_CN.md b/build/README_CN.md new file mode 100644 index 000000000..fe10db852 --- /dev/null +++ b/build/README_CN.md @@ -0,0 +1,53 @@ +# 运行文件 + +[English](README.md) + +构建产物保存在 `/bin`。Release、Debug 和 sanitizer 构建使用 +独立目录。将同一次构建的程序和插件复制到运行目录的 `bin/`,并准备 `conf/`;使用 +业务资源的应用还需要 `resource/`。本目录保存示例配置、资源与工具,不追踪生成的二进制文件。 + +## 启动一个应用 + +Shell 和 Windows 脚本使用相同参数: + +```text +run.sh [runtime-directory] +run.bat [runtime-directory] +``` + +运行目录默认为脚本所在目录。显式传入的相对路径以调用者的工作目录为基准。 +Release 使用 `bin/app`(Windows 为 `app.exe`),Debug 使用 `bin/app_d` +(Windows 为 `app_d.exe`)。脚本读取 `conf/.app.conf` 和 `conf/log.conf`, +在前台运行应用;`name` 同时作为 `--name` 的值。使用 TOML 配置、不同的进程名称或 +其他启动参数时,直接调用程序。 + +按[Sample1 快速开始](../docs/get-started/quick-start_CN.md)准备运行目录后,在仓库根目录执行: + +```sh +sh build/run.sh Release sample1 1.0.1.1 run/sample1 +``` + +Windows 使用 `build\run.bat Release sample1 1.0.1.1 run\sample1`。 +使用应用前,检查初始化日志。脚本的路径检查不验证插件、业务配置或服务就绪状态。 + +## 停止一个应用 + +macOS/Linux 优先使用 Ctrl+C,Windows 优先在应用控制台输入 `exit`。 +确认目标进程的 PID 后,使用 `kill.sh ` 请求 `SIGTERM`;`kill.bat ` 会强制终止 +该 PID。两个脚本都只接受一个显式 PID,并拒绝其他可执行文件名。执行前重新确认 PID 的 +可执行文件与命令行;进程退出后,PID 可能被复用。脚本不按名称通配批量停止进程。 + +## 迁移旧命令 + +- 将 `rund.sh` / `rund.bat` 改为 `run.sh Debug ...` / `run.bat Debug ...`。 +- 将 `sample1.sh`、`mysql_sample.sh` 和 `sample5http_test.sh` 改为 + `run.sh Debug `;名称分别为 `sample1`、`mysql_sample`、`sample5`。 +- 旧版无参数五服务启动顺序引用了不存在的 `plugin_conf/`,Release 与 Debug 的总线 ID + 也不一致。现在需要显式传入每个应用的名称与总线 ID,并按目标环境安排启动顺序。 + 新脚本不再将应用转为守护进程。 +- 使用 `cmake --build --target clean` 清理选定构建目录, + 替代 `vc_clear.bat`。 +- 容器构建文件和集群示例已移至 [deployment/](../deployment/README_CN.md)。 + +`docs/site/legacy-source/` 按原始字节保留历史文章,其中的 `bin/rund.*` 命令不再适用, +请使用上面的当前命令。 diff --git a/build/kill.bat b/build/kill.bat index e033f71b3..a8be271ee 100755 --- a/build/kill.bat +++ b/build/kill.bat @@ -1,5 +1,20 @@ -cd /d %~dp0 - @echo off - -taskkill /f /im app* \ No newline at end of file +setlocal +if "%~1"=="" goto usage +if not "%~2"=="" goto usage +for /f "delims=0123456789" %%p in ("%~1") do goto usage +set "pid=%~1" +if "%pid:~0,1%"=="0" goto usage +if "%~1"=="1" goto usage +for /f "tokens=1 delims=," %%p in ('tasklist /fi "PID eq %~1" /fo csv /nh') do ( + if /i "%%~p"=="app.exe" goto stop + if /i "%%~p"=="app_d.exe" goto stop +) +echo PID %~1 is not an app.exe or app_d.exe process; refusing to stop it. 1>&2 +exit /b 1 +:stop +taskkill /f /pid %~1 +exit /b %errorlevel% +:usage +echo Usage: %~nx0 ^ 1>&2 +exit /b 2 diff --git a/build/kill.sh b/build/kill.sh index c492c2731..80711fce1 100755 --- a/build/kill.sh +++ b/build/kill.sh @@ -1,3 +1,16 @@ -kill -9 $(pidof *_server) +#!/bin/sh +set -eu -ps aux | grep *_server \ No newline at end of file +if [ "$#" -ne 1 ]; then + echo "Usage: $0 " >&2 + exit 2 +fi +case "$1" in + ''|*[!0-9]*|0|1|0*) echo "Supply one application PID greater than 1" >&2; exit 2 ;; +esac +command_name=$(ps -p "$1" -o comm=) || exit 1 +command_name=${command_name##*/} +case "$command_name" in + app|app_d) kill -TERM "$1" ;; + *) echo "PID $1 is not an app or app_d process; refusing to stop it" >&2; exit 1 ;; +esac diff --git a/build/mysql_sample.sh b/build/mysql_sample.sh deleted file mode 100644 index 4984d3607..000000000 --- a/build/mysql_sample.sh +++ /dev/null @@ -1,13 +0,0 @@ -export LC_ALL="C" - -# The default zone is 1001 - -CHANNEL_ID=1 -ZONE_ID=1 - -echo Starting http_server... -./bin/app_d --busid=1.0.1.1 --name=mysql_sample --app_conf=conf/mysql_sample.app.conf - -echo All processes are launching... - -ps aux | grep app_d diff --git a/build/run.bat b/build/run.bat index db5bd8c76..6a750de4e 100755 --- a/build/run.bat +++ b/build/run.bat @@ -1,34 +1,26 @@ -cd /d %~dp0 - @echo off - -REM the default zone is 1001 - -set CHANNEL_ID=1 -set ZONE_ID=1 - -cd Release - -echo Starting master... -start "master" bin/app.exe -x --busid=1.0.1.1 --name=master_server --app_conf=plugin_conf/master.app.conf -choice /t 5 /d y /n >nul - -echo Starting world... -start "world" bin/app.exe -x --busid=1.1.30.1 --name=world_server --app_conf=plugin_conf/world.app.conf -choice /t 5 /d y /n >nul - -echo Starting login... -start "login" bin/app.exe -x --busid=1.1.31.1 --name=login_server --app_conf=plugin_conf/login.app.conf -choice /t 5 /d y /n >nul - -echo Starting proxy... -start "proxy" bin/app.exe -x --busid=1.1.32.1 --name=proxy_server --app_conf=plugin_conf/proxy.app.conf -choice /t 5 /d y /n >nul - -echo Starting game... -start "game" bin/app.exe -x --busid=1.1.33.1 --name=game_server --app_conf=plugin_conf/game.app.conf -choice /t 5 /d y /n >nul - -echo All processes are launching... - -cd \ No newline at end of file +setlocal +if "%~3"=="" goto usage +if not "%~5"=="" goto usage +set "binary=" +if "%~1"=="Release" set "binary=bin\app.exe" +if "%~1"=="Debug" set "binary=bin\app_d.exe" +if not defined binary goto usage +echo(%~2| findstr /r /x "[a-zA-Z0-9_-][a-zA-Z0-9_-]*" >nul || goto usage +set "runtime=%~dp0" +if not "%~4"=="" set "runtime=%~4" +pushd "%runtime%" || exit /b 1 +if not exist "%binary%" goto missing +if not exist "conf\%~2.app.conf" goto missing +if not exist "conf\log.conf" goto missing +"%binary%" "--busid=%~3" "--name=%~2" "--app_conf=conf/%~2.app.conf" --log_conf=conf/log.conf +set "result=%errorlevel%" +popd +exit /b %result% +:missing +echo Missing executable or configuration in "%CD%". 1>&2 +popd +exit /b 1 +:usage +echo Usage: %~nx0 ^ ^ ^ [runtime-directory] 1>&2 +exit /b 2 diff --git a/build/run.sh b/build/run.sh index 43fc62121..019cecf6d 100755 --- a/build/run.sh +++ b/build/run.sh @@ -1,29 +1,26 @@ -cd bin - -export LC_ALL="C" - -#The default zone is 1001 - -CHANNEL_ID=1 -ZONE_ID=1 - -echo Starting master... -./bin/app -d --busid=1.0.1.1 --name=master_server --app_conf=plugin_conf/master.app.conf - -echo Starting world... -./bin/app -d --busid=1.1.30.1 --name=world_server --app_conf=plugin_conf/world.app.conf - -echo Starting login... -./bin/app -d --busid=1.1.31.1 --name=login_server --app_conf=plugin_conf/login.app.conf - -echo Starting proxy... -./bin/app -d --busid=1.1.32.1 --name=proxy_server --app_conf=plugin_conf/proxy.app.conf - -echo Starting game... -./bin/app -d --busid=1.1.33.1 --name=game_server --app_conf=plugin_conf/game.app.conf - -echo All processes are launching... - -ps aux | grep app - -cd ../ \ No newline at end of file +#!/bin/sh +set -eu + +if [ "$#" -lt 3 ] || [ "$#" -gt 4 ]; then + echo "Usage: $0 [runtime-directory]" >&2 + exit 2 +fi +case "$1" in + Release) binary=./bin/app ;; + Debug) binary=./bin/app_d ;; + *) echo "Configuration must be Release or Debug" >&2; exit 2 ;; +esac +case "$2" in + ''|*[!a-zA-Z0-9_-]*) echo "Name must contain only letters, digits, _ or -" >&2; exit 2 ;; +esac +if [ "$#" -eq 4 ]; then + cd -- "$4" +else + CDPATH='' cd -- "$(dirname -- "$0")" +fi +[ -x "$binary" ] || { echo "Missing executable: $binary" >&2; exit 1; } +for config in "conf/$2.app.conf" conf/log.conf; do + [ -f "$config" ] || { echo "Missing configuration: $config" >&2; exit 1; } +done +export LC_ALL=C +exec "$binary" "--busid=$3" "--name=$2" "--app_conf=conf/$2.app.conf" --log_conf=conf/log.conf diff --git a/build/rund.bat b/build/rund.bat deleted file mode 100755 index 00e04dd0f..000000000 --- a/build/rund.bat +++ /dev/null @@ -1,32 +0,0 @@ -REM This file is generated by gcm tools. -REM Please DO NOT modify it manually. - -cd /d %~dp0 - -@echo off - -REM the default zone is 1001 - -echo Starting master... -start "master" bin/app_d.exe -x --busid=1.0.1.1 --name=master_server --app_conf=plugin_conf/master.app.conf -choice /t 5 /d y /n >nul - -echo Starting world... -start "world" bin/app_d.exe -x --busid=1.1.30.1 --name=world_server --app_conf=plugin_conf/world.app.conf -choice /t 5 /d y /n >nul - -echo Starting login... -start "login" bin/app_d.exe -x --busid=1.1.32.1 --name=login_server --app_conf=plugin_conf/login.app.conf -choice /t 5 /d y /n >nul - -echo Starting proxy... -start "proxy" bin/app_d.exe -x --busid=1.1.33.1 --name=proxy_server --app_conf=plugin_conf/proxy.app.conf -choice /t 5 /d y /n >nul - -echo Starting game... -start "game" bin/app_d.exe -x --busid=1.1.31.1 --name=game_server --app_conf=plugin_conf/game.app.conf -choice /t 5 /d y /n >nul - -echo All processes started... - -cd ../ \ No newline at end of file diff --git a/build/rund.sh b/build/rund.sh deleted file mode 100755 index 882c7e136..000000000 --- a/build/rund.sh +++ /dev/null @@ -1,29 +0,0 @@ -cd debug - -export LC_ALL="C" - -#The default zone is 1001 - -CHANNEL_ID=1 -ZONE_ID=1 - -echo Starting master... -./bin/app_d -d --busid=1.0.1.1 --name=master_server --app_conf=plugin_conf/master.app.conf - -echo Starting world... -./bin/app_d -d --busid=1.1.30.1 --name=world_server --app_conf=plugin_conf/world.app.conf - -echo Starting login... -./bin/app_d -d --busid=1.1.31.1 --name=login_server --app_conf=plugin_conf/login.app.conf - -echo Starting proxy... -./bin/app_d -d --busid=1.1.32.1 --name=proxy_server --app_conf=plugin_conf/proxy.app.conf - -echo Starting game... -./bin/app_d -d --busid=1.1.33.1 --name=game_server --app_conf=plugin_conf/game.app.conf - -echo All processes are launching... - -ps aux | grep app_d - -cd ../ \ No newline at end of file diff --git a/build/sample1.sh b/build/sample1.sh deleted file mode 100755 index d35eef3fe..000000000 --- a/build/sample1.sh +++ /dev/null @@ -1,13 +0,0 @@ -export LC_ALL="C" - -# The default zone is 1001 - -CHANNEL_ID=1 -ZONE_ID=1 - -echo Starting sample1... -./bin/app_d --busid=1.0.1.1 --name=sample1 --app_conf=conf/sample1.app.conf - -echo All processes are launching... - -ps aux | grep app_d diff --git a/build/sample5http_test.sh b/build/sample5http_test.sh deleted file mode 100755 index 953ddc873..000000000 --- a/build/sample5http_test.sh +++ /dev/null @@ -1,13 +0,0 @@ -export LC_ALL="C" - -# The default zone is 1001 - -CHANNEL_ID=1 -ZONE_ID=1 - -echo Starting http_server... -./bin/app_d -d --busid=1.0.1.1 --name=sample5 --app_conf=conf/Sample5.app.conf - -echo All processes are launching... - -ps aux | grep app_d diff --git a/build/vc_clear.bat b/build/vc_clear.bat deleted file mode 100755 index 1f671d376..000000000 --- a/build/vc_clear.bat +++ /dev/null @@ -1,14 +0,0 @@ -@echo off -echo clearing the building temp files, please wait for a while. - -del /f /q /s *.obj -del /f /q /s *.pdb -del /f /q /s *.idb -del /f /q /s *.pch -del /f /q /s *.ilk -del /f /q /s *.dll -del /f /q /s *.exe - - -echo clear finished -pause \ No newline at end of file diff --git a/Dockerfile b/deployment/Dockerfile similarity index 91% rename from Dockerfile rename to deployment/Dockerfile index 1b85181b8..5eb98f226 100644 --- a/Dockerfile +++ b/deployment/Dockerfile @@ -1,5 +1,5 @@ # --build-arg 来设置参数 -# docker build -t ark:escort --build-arg -f ./Dockerfile . +# From the repository root: docker build -t ark:escort -f deployment/Dockerfile . FROM docker/ark-alpine-build:latest AS Builder diff --git a/deployment/README.md b/deployment/README.md new file mode 100644 index 000000000..6c1112d06 --- /dev/null +++ b/deployment/README.md @@ -0,0 +1,29 @@ +# Deployment examples + +[简体中文](README_CN.md) + +This directory groups the existing container recipes and Kubernetes examples. +The YAML files retain their existing services, images, namespaces, settings and +resources; their in-tree plugin library stems follow the current build names. +External business-plugin names remain unchanged. Review these environment-specific +examples before use; moving them does not establish working deployment acceptance. + +Run image build commands from the repository root so `COPY .` keeps the source +checkout as its build context: + +```sh +docker build -t docker/ark-alpine-build:latest -f deployment/docker/ark-alpine-build . +docker build -t docker/ark-alpine-runtime:latest -f deployment/docker/ark-alpine-runtime . +docker build -t ark:escort -f deployment/Dockerfile . +``` + +The application Dockerfile still uses the build image for both stages. The +separate runtime recipe is retained as an existing alternative; it is not selected +by the application recipe. These recipes retain their pre-existing dependency +and image choices and have not been validated against a container engine here. + +Cluster example paths are now `deployment/ark_consul.yaml`, +`deployment/photon_config.yaml`, `deployment/photon_game_deployment.yaml` and +`deployment/photon_master_deployment.yaml`. Update external build commands that +used the root `Dockerfile`, `docker/` or `kubernetes/` paths. Runtime launch helpers +are documented in [build/README.md](../build/README.md). diff --git a/deployment/README_CN.md b/deployment/README_CN.md new file mode 100644 index 000000000..12bd7e4ca --- /dev/null +++ b/deployment/README_CN.md @@ -0,0 +1,23 @@ +# 部署示例 + +[English](README.md) + +本目录集中保存原有容器构建文件与 Kubernetes 示例。YAML 中的服务、镜像、命名空间、 +配置和资源保持原样;仓库内插件的动态库名称与当前构建名称对齐。外部业务插件名称 +保持原样。使用前需要检查目标环境;目录迁移不代表部署验收通过。 + +从仓库根目录执行镜像构建命令,使 `COPY .` 继续以源码仓库作为构建上下文: + +```sh +docker build -t docker/ark-alpine-build:latest -f deployment/docker/ark-alpine-build . +docker build -t docker/ark-alpine-runtime:latest -f deployment/docker/ark-alpine-runtime . +docker build -t ark:escort -f deployment/Dockerfile . +``` + +应用 Dockerfile 的两个阶段仍使用构建镜像。单独的 runtime 构建文件作为原有选项保留, +应用构建文件没有选用它。这些构建文件保留了原有依赖与镜像选择,本次未通过容器引擎验证。 + +集群示例路径改为 `deployment/ark_consul.yaml`、`deployment/photon_config.yaml`、 +`deployment/photon_game_deployment.yaml` 和 `deployment/photon_master_deployment.yaml`。 +外部构建命令中的根目录 `Dockerfile`、`docker/` 和 `kubernetes/` 路径需要同步更新。 +运行脚本说明见 [build/README_CN.md](../build/README_CN.md)。 diff --git a/kubernetes/ark_consul.yaml b/deployment/ark_consul.yaml similarity index 100% rename from kubernetes/ark_consul.yaml rename to deployment/ark_consul.yaml diff --git a/docker/ark-alpine-build b/deployment/docker/ark-alpine-build similarity index 100% rename from docker/ark-alpine-build rename to deployment/docker/ark-alpine-build diff --git a/docker/ark-alpine-runtime b/deployment/docker/ark-alpine-runtime similarity index 100% rename from docker/ark-alpine-runtime rename to deployment/docker/ark-alpine-runtime diff --git a/kubernetes/photon_config.yaml b/deployment/photon_config.yaml similarity index 100% rename from kubernetes/photon_config.yaml rename to deployment/photon_config.yaml diff --git a/kubernetes/photon_game_deployment.yaml b/deployment/photon_game_deployment.yaml similarity index 100% rename from kubernetes/photon_game_deployment.yaml rename to deployment/photon_game_deployment.yaml diff --git a/kubernetes/photon_master_deployment.yaml b/deployment/photon_master_deployment.yaml similarity index 100% rename from kubernetes/photon_master_deployment.yaml rename to deployment/photon_master_deployment.yaml diff --git a/docs/project-layout.md b/docs/project-layout.md index 1a766366d..e3eebb29f 100644 --- a/docs/project-layout.md +++ b/docs/project-layout.md @@ -27,6 +27,8 @@ build's artifacts into the runtime's `bin/` directory. | `tests/network/` | Network and logging regressions | | `tests/consumer/` | An independent project consuming the public SDK | | `examples/` | Application examples | +| `build/` | Runtime configuration, resources, tools and [launch helpers](../build/README.md) | +| `deployment/` | Container recipes and Kubernetes examples | Include public headers as `` or ``. Do not add implementation directories to an application's include path. Generated diff --git a/docs/project-layout_CN.md b/docs/project-layout_CN.md index 1b68005dc..eef556230 100644 --- a/docs/project-layout_CN.md +++ b/docs/project-layout_CN.md @@ -25,6 +25,8 @@ ark 使用 C++20。核心与官方插件放在本仓库,业务插件放在应 | `tests/network/` | 网络与日志回归测试 | | `tests/consumer/` | 独立使用公开 SDK 的示例项目 | | `examples/` | 应用示例 | +| `build/` | 运行配置、资源、工具与[启动脚本](../build/README_CN.md) | +| `deployment/` | 容器构建文件与 Kubernetes 示例 | 使用 ``、`` 等公开路径包含头文件, 不需要把实现目录加入应用的包含路径。Protobuf 生成文件位于构建目录,由 `ark::proto` 提供。 diff --git a/docs/project/changelog.md b/docs/project/changelog.md index 8139213f2..f0774e1ae 100644 --- a/docs/project/changelog.md +++ b/docs/project/changelog.md @@ -1,5 +1,17 @@ # changelogs +## Unreleased + +### Upgrade notes + +- Container recipes and Kubernetes examples now live in `deployment/`. Use + `docker build -f deployment/Dockerfile .` from the repository root, and update + external references to the former `docker/` and `kubernetes/` directories. +- Runtime helpers now launch one foreground application with explicit build mode, + name and Bus ID. Replace `rund.*` and sample wrappers with `run.* Debug ...`; + stop helpers require one explicit PID. See [runtime migration](../../build/README.md#migrate-old-helper-commands) + for the removed five-service sequence and Visual Studio cleanup command. + ## version 0.9 - Fix `HeartBeatManager` remove mistake(Thanks @sks) diff --git a/docs/project/changelog_CN.md b/docs/project/changelog_CN.md index 519ebfbf9..5bbe191ce 100644 --- a/docs/project/changelog_CN.md +++ b/docs/project/changelog_CN.md @@ -1,5 +1,16 @@ # Changelogs +## 未发布 + +### 升级说明 + +- 容器构建文件与 Kubernetes 示例已集中到 `deployment/`。从仓库根目录执行 + `docker build -f deployment/Dockerfile .`,并更新外部命令中的旧 `docker/`、 + `kubernetes/` 路径。 +- 运行脚本现在按显式构建模式、名称和总线 ID 启动一个前台应用。将 `rund.*` 与示例包装 + 脚本改为 `run.* Debug ...`;停止脚本要求显式传入一个 PID。旧五服务启动顺序与 + Visual Studio 清理命令的替代方式见[运行脚本迁移](../../build/README_CN.md#迁移旧命令)。 + ### version 0.9 - Fix `HeartBeatManager` remove mistake(Thanks @sks) diff --git a/docs/reference/directory-structure.md b/docs/reference/directory-structure.md index 3c48dd4a2..f355d1b4a 100644 --- a/docs/reference/directory-structure.md +++ b/docs/reference/directory-structure.md @@ -21,6 +21,8 @@ Build artifacts belong to each CMake build directory: `cmake -S . -B out/release | `tests/network/` | Network and logging regressions | | `tests/consumer/` | An independent project consuming the public SDK | | `examples/` | Application examples | +| `build/` | Runtime configuration, resources, tools and [launch helpers](../../build/README.md) | +| `deployment/` | Container recipes and Kubernetes examples | Include public headers as `` or ``. Do not add implementation directories to an application's include path. Generated diff --git a/docs/reference/directory-structure_CN.md b/docs/reference/directory-structure_CN.md index 9519e41d2..3fd3ea075 100644 --- a/docs/reference/directory-structure_CN.md +++ b/docs/reference/directory-structure_CN.md @@ -20,6 +20,8 @@ ark 使用 C++20。核心与官方插件放在本仓库,业务插件放在应 | `tests/network/` | 网络与日志回归测试 | | `tests/consumer/` | 独立使用公开 SDK 的示例项目 | | `examples/` | 应用示例 | +| `build/` | 运行配置、资源、工具与[启动脚本](../../build/README_CN.md) | +| `deployment/` | 容器构建文件与 Kubernetes 示例 | 使用 ``、`` 等公开路径包含头文件, 不需要把实现目录加入应用的包含路径。Protobuf 生成文件位于构建目录,由 `ark::proto` 提供。 diff --git a/tests/runtime/scripts.test.mjs b/tests/runtime/scripts.test.mjs new file mode 100644 index 000000000..ab2a8090c --- /dev/null +++ b/tests/runtime/scripts.test.mjs @@ -0,0 +1,83 @@ +import assert from 'node:assert/strict'; +import { mkdtempSync, mkdirSync, writeFileSync, readFileSync, realpathSync, rmSync } from 'node:fs'; +import { tmpdir } from 'node:os'; +import { join, resolve } from 'node:path'; +import { spawnSync } from 'node:child_process'; +import { test } from 'node:test'; + +const root = resolve(import.meta.dirname, '../..'); +const run = join(root, 'build/run.sh'); +const stop = join(root, 'build/kill.sh'); + +function fixture(t) { + const dir = mkdtempSync(join(tmpdir(), 'ark runtime ')); + t.after(() => rmSync(dir, { recursive: true, force: true })); + mkdirSync(join(dir, 'bin')); + mkdirSync(join(dir, 'conf')); + writeFileSync(join(dir, 'conf/sample1.app.conf'), ''); + writeFileSync(join(dir, 'conf/log.conf'), ''); + const binary = '#!/bin/sh\nprintf "%s\\n" "$PWD" "$LC_ALL" "$0" "$@"\nexit 17\n'; + for (const name of ['app', 'app_d']) { + writeFileSync(join(dir, 'bin', name), binary, { mode: 0o755 }); + } + return dir; +} + +for (const [configuration, binary] of [['Release', 'app'], ['Debug', 'app_d']]) { + test(`${configuration} selects one application in the explicit runtime directory`, (t) => { + const dir = fixture(t); + const result = spawnSync('sh', [run, configuration, 'sample1', '1.0.1.1', dir], { + cwd: tmpdir(), encoding: 'utf8', + }); + assert.equal(result.status, 17, result.stderr); + const [cwd, locale, executable, ...args] = result.stdout.trim().split('\n'); + assert.equal(realpathSync(cwd), realpathSync(dir)); + assert.equal(locale, 'C'); + assert.equal(realpathSync(resolve(cwd, executable)), realpathSync(join(dir, 'bin', binary))); + assert.deepEqual(args, [ + '--busid=1.0.1.1', '--name=sample1', '--app_conf=conf/sample1.app.conf', + '--log_conf=conf/log.conf', + ]); + }); +} + +test('default runtime is the script directory and ignores the caller working directory', (t) => { + const dir = fixture(t); + writeFileSync(join(dir, 'run.sh'), readFileSync(run)); + const result = spawnSync('sh', [join(dir, 'run.sh'), 'Release', 'sample1', '1.0.1.1'], { + cwd: tmpdir(), encoding: 'utf8', + }); + assert.equal(result.status, 17, result.stderr); + assert.match(result.stdout, /--app_conf=conf\/sample1\.app\.conf/); +}); + +test('missing configuration or executable fails before launching', (t) => { + const dir = fixture(t); + rmSync(join(dir, 'conf/log.conf')); + let result = spawnSync('sh', [run, 'Release', 'sample1', '1.0.1.1', dir], { encoding: 'utf8' }); + assert.equal(result.status, 1); + assert.match(result.stderr, /Missing configuration/); + rmSync(join(dir, 'bin/app')); + result = spawnSync('sh', [run, 'Release', 'sample1', '1.0.1.1', dir], { encoding: 'utf8' }); + assert.equal(result.status, 1); + assert.match(result.stderr, /Missing executable/); +}); + +test('invalid arguments are rejected before starting or stopping a process', () => { + for (const args of [[], ['Other', 'sample1', '1.0.1.1'], ['Release', '../sample1', '1.0.1.1']]) { + assert.equal(spawnSync('sh', [run, ...args]).status, 2); + } + for (const args of [[], ['0'], ['1'], ['-1'], ['00123'], ['all'], ['123', '456']]) { + assert.equal(spawnSync('sh', [stop, ...args]).status, 2); + } +}); + +test('stop refuses another executable without sending a signal', (t) => { + const dir = fixture(t); + writeFileSync(join(dir, 'bin/ps'), '#!/bin/sh\nprintf "unrelated-service\\n"\n', { mode: 0o755 }); + const result = spawnSync('sh', [stop, '12345'], { + env: { ...process.env, PATH: `${join(dir, 'bin')}:${process.env.PATH}` }, encoding: 'utf8', + }); + assert.equal(result.status, 1); + assert.match(result.stderr, /refusing to stop/); +});