From 28337c969403e29f4782b3e0abaf7518b68465fa Mon Sep 17 00:00:00 2001 From: augushong Date: Wed, 27 May 2026 20:49:13 +0800 Subject: [PATCH] =?UTF-8?q?refactor(stack):=20default=20=E6=A8=A1=E5=BC=8F?= =?UTF-8?q?=E6=94=B9=E4=B8=BA=20php=20think=20run=EF=BC=8C=E5=8E=9F=20Dock?= =?UTF-8?q?er=20=E9=83=A8=E7=BD=B2=E6=8B=86=E5=88=86=E4=B8=BA=20docker-ser?= =?UTF-8?q?ve=20=E6=A8=A1=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - source/stack/default/ 重命名为 docker-serve,保留 Dockerfile/docker-compose/CI/run.sh - 新 default 模式仅提供 CI 文件(流水线中自动切换 docker-serve 再构建) - 更新 stack.json 增加 docker-serve 模式声明 - 更新 README.md 同步模式说明 --- source/stack/README.md | 25 ++- .../.gitea/workflows/build-and-deploy.yml | 4 + .../.gitea/workflows/build-and-deploy.yml | 149 ++++++++++++++++++ .../{default => docker-serve}/Dockerfile | 0 .../docker-compose.yaml | 0 .../source/docker/run.sh | 0 source/stack/stack.json | 6 +- 7 files changed, 176 insertions(+), 8 deletions(-) create mode 100644 source/stack/docker-serve/.gitea/workflows/build-and-deploy.yml rename source/stack/{default => docker-serve}/Dockerfile (100%) rename source/stack/{default => docker-serve}/docker-compose.yaml (100%) rename source/stack/{default => docker-serve}/source/docker/run.sh (100%) diff --git a/source/stack/README.md b/source/stack/README.md index bba6183..6337d62 100644 --- a/source/stack/README.md +++ b/source/stack/README.md @@ -1,26 +1,37 @@ # Stack 模式目录规范 -本目录用于维护“模式化生效文件”,由 `php think admin:stack:mode` 命令读取并覆盖到仓库根目录。 +本目录用于维护"模式化生效文件",由 `php think admin:stack:mode` 命令读取并覆盖到仓库根目录。 ## 目录结构 - `source/stack/stack.json`:全局清单,定义 `default_mode`、`managed_files`、`modes` 元数据。 -- `source/stack/default/`:默认行为基线目录。 -- `source/stack/{mode}/`:具体模式目录,按“仓库相对路径”放置文件。 +- `source/stack/default/`:默认行为基线目录(`php think run`,纯 PHP 内置服务器运行)。 +- `source/stack/{mode}/`:具体模式目录,按"仓库相对路径"放置文件。 ## default 目录规则(强约束) - `source/stack/default/` 必须与代码库默认行为一致。 -- 当默认行为文件变更时(如 `Dockerfile`、`docker-compose.yaml`、`.gitea/workflows/build-and-deploy.yml`),必须同步更新 `default` 目录对应文件。 +- 默认行为为 `php think run`(ThinkPHP 内置服务器),不依赖 Docker。 +- 当默认行为文件变更时(如 `.gitea/workflows/build-and-deploy.yml`),必须同步更新 `default` 目录对应文件。 - 该规则通过目录维护规范与代码评审保障,不作为每次切换命令的运行时阻断条件。 ## 模式覆盖规则 - 仅允许覆盖 `stack.json` 的 `managed_files` 中声明的文件。 -- 切换时按“目标模式优先,default 模式兜底”解析最终文件内容: +- 切换时按以下优先级解析最终文件: - 目标模式提供某文件:使用目标模式文件; - - 目标模式未提供某文件:回落使用 `default` 目录对应文件。 -- 首期固定模式:`default`、`full`、`base-build`。 + - 目标模式未提供某文件:回落使用 `default` 目录对应文件; + - 两者均未提供:从根目录删除该文件(带备份,可回滚)。 + +## 可用模式 + +| 模式 | 说明 | +|------|------| +| `default` | 默认基线,`php think run` 运行,无 Docker 文件 | +| `docker-serve` | Docker 部署模式(基于基础镜像,nginx+php-fpm) | +| `full` | 全量构建模式(兼容历史行为,从 PHP 镜像从头构建) | +| `base-build` | 基础镜像 + 应用构建模式(author_only) | +| `docker-dev` | Docker 开发模式(nginx+php-fpm+MySQL+Redis+phpMyAdmin+Xdebug) | ## 基础镜像说明 diff --git a/source/stack/default/.gitea/workflows/build-and-deploy.yml b/source/stack/default/.gitea/workflows/build-and-deploy.yml index bff4cbc..f036fe3 100644 --- a/source/stack/default/.gitea/workflows/build-and-deploy.yml +++ b/source/stack/default/.gitea/workflows/build-and-deploy.yml @@ -22,6 +22,10 @@ jobs: with: fetch-depth: 1 + - name: 切换到 docker-serve 模式 + shell: bash + run: php think admin:stack:mode apply docker-serve + - name: 生成 .env shell: bash env: diff --git a/source/stack/docker-serve/.gitea/workflows/build-and-deploy.yml b/source/stack/docker-serve/.gitea/workflows/build-and-deploy.yml new file mode 100644 index 0000000..bff4cbc --- /dev/null +++ b/source/stack/docker-serve/.gitea/workflows/build-and-deploy.yml @@ -0,0 +1,149 @@ +name: build-and-deploy + +on: + push: + workflow_dispatch: + +env: + REMOTE_APP_DIR: /data/projects/ulthon_admin/docker + PACKAGE_NAME: ulthon_admin_release.tar.gz + COMPOSE_PROJECT_NAME: ulthon_admin + DB_HOSTNAME: host.docker.internal + +jobs: + deploy_host15: + name: 直传代码并部署到 Host15 + runs-on: main + container: + image: ulthon/debian-php82-composer-node20-act:20260503082548 + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 1 + + - name: 生成 .env + shell: bash + env: + MYSQL_PASSWORD: ${{ secrets.MYSQL_PASSWORD }} + DB_HOSTNAME: ${{ env.DB_HOSTNAME }} + run: | + set -euo pipefail + cp .example.env .env + + awk -v host="$DB_HOSTNAME" -v newpwd="$MYSQL_PASSWORD" ' + BEGIN { has_host = 0; has_pwd = 0 } + $0 ~ /^HOSTNAME=/ { + print "HOSTNAME=" host + has_host = 1 + next + } + $0 ~ /^PASSWORD=/ { + print "PASSWORD=" newpwd + has_pwd = 1 + next + } + { print } + END { + if (!has_host) print "HOSTNAME=" host + if (!has_pwd) print "PASSWORD=" newpwd + }' .env > .env.tmp + + mv .env.tmp .env + + - name: 打包发布文件 + shell: bash + env: + PACKAGE_NAME: ${{ env.PACKAGE_NAME }} + run: | + set -euo pipefail + + composer config -g repos.packagist composer https://nexus.hl7.top:1243/repository/composer-proxy/ + composer install --no-dev --no-interaction --prefer-dist --optimize-autoloader + + TMP_PACKAGE="/tmp/${PACKAGE_NAME}" + rm -f "$TMP_PACKAGE" "$PACKAGE_NAME" + + tar -czf "$TMP_PACKAGE" \ + --exclude="$PACKAGE_NAME" \ + --exclude-vcs \ + --exclude="./runtime/*" \ + --exclude="./.trae/*" \ + --exclude="./source/clients/uniapp/node_modules/*" \ + . + cp -f "$TMP_PACKAGE" "$PACKAGE_NAME" + + - name: 创建远端目录 + uses: appleboy/ssh-action@v0.1.10 + env: + REMOTE_APP_DIR: ${{ env.REMOTE_APP_DIR }} + with: + host: ${{ secrets.UL_HOST15_IP }} + username: ${{ secrets.UL_HOST15_USER }} + password: ${{ secrets.UL_HOST15_PASSWORD }} + port: ${{ secrets.UL_HOST15_PORT }} + envs: REMOTE_APP_DIR + script: | + set -euo pipefail + mkdir -p "${REMOTE_APP_DIR}/incoming" + mkdir -p "${REMOTE_APP_DIR}/releases" + + - name: 上传发布包与 compose + uses: appleboy/scp-action@v0.1.7 + env: + REMOTE_APP_DIR: ${{ env.REMOTE_APP_DIR }} + PACKAGE_NAME: ${{ env.PACKAGE_NAME }} + with: + host: ${{ secrets.UL_HOST15_IP }} + username: ${{ secrets.UL_HOST15_USER }} + password: ${{ secrets.UL_HOST15_PASSWORD }} + port: ${{ secrets.UL_HOST15_PORT }} + source: "${{ env.PACKAGE_NAME }},docker-compose.yaml" + target: "${{ env.REMOTE_APP_DIR }}/incoming" + overwrite: true + + - name: 远端解压并启动 + uses: appleboy/ssh-action@v0.1.10 + env: + REMOTE_APP_DIR: ${{ env.REMOTE_APP_DIR }} + PACKAGE_NAME: ${{ env.PACKAGE_NAME }} + COMPOSE_PROJECT_NAME: ${{ env.COMPOSE_PROJECT_NAME }} + GITHUB_RUN_ID: ${{ github.run_id }} + with: + host: ${{ secrets.UL_HOST15_IP }} + username: ${{ secrets.UL_HOST15_USER }} + password: ${{ secrets.UL_HOST15_PASSWORD }} + port: ${{ secrets.UL_HOST15_PORT }} + timeout: 120s + command_timeout: 60m + envs: REMOTE_APP_DIR,PACKAGE_NAME,COMPOSE_PROJECT_NAME,GITHUB_RUN_ID + script: | + set -euo pipefail + + RELEASE_DIR="${REMOTE_APP_DIR}/releases/${GITHUB_RUN_ID}" + PACKAGE_PATH="${REMOTE_APP_DIR}/incoming/${PACKAGE_NAME}" + COMPOSE_PATH="${REMOTE_APP_DIR}/incoming/docker-compose.yaml" + + rm -rf "${RELEASE_DIR}" + mkdir -p "${RELEASE_DIR}" + + tar -xzf "${PACKAGE_PATH}" -C "${RELEASE_DIR}" + + if [ -f "${COMPOSE_PATH}" ]; then + cp -f "${COMPOSE_PATH}" "${RELEASE_DIR}/docker-compose.yaml" + fi + + cd "${RELEASE_DIR}" + export COMPOSE_PROJECT_NAME + + docker compose down || true + docker compose up -d --build --remove-orphans + + docker compose ps + docker compose exec -T ulthon_admin test -f /var/www/html/vendor/autoload.php + docker compose exec -T ulthon_admin php -r "require '/var/www/html/vendor/autoload.php'; echo 'autoload-ok'.PHP_EOL;" + docker compose logs --tail=80 ulthon_admin + + ln -sfn "${RELEASE_DIR}" "${REMOTE_APP_DIR}/current" + + ls -1dt "${REMOTE_APP_DIR}/releases"/* 2>/dev/null | tail -n +6 | xargs -r rm -rf diff --git a/source/stack/default/Dockerfile b/source/stack/docker-serve/Dockerfile similarity index 100% rename from source/stack/default/Dockerfile rename to source/stack/docker-serve/Dockerfile diff --git a/source/stack/default/docker-compose.yaml b/source/stack/docker-serve/docker-compose.yaml similarity index 100% rename from source/stack/default/docker-compose.yaml rename to source/stack/docker-serve/docker-compose.yaml diff --git a/source/stack/default/source/docker/run.sh b/source/stack/docker-serve/source/docker/run.sh similarity index 100% rename from source/stack/default/source/docker/run.sh rename to source/stack/docker-serve/source/docker/run.sh diff --git a/source/stack/stack.json b/source/stack/stack.json index a65e67d..2a7e6e4 100644 --- a/source/stack/stack.json +++ b/source/stack/stack.json @@ -12,7 +12,11 @@ ], "modes": { "default": { - "description": "代码库默认行为基线", + "description": "代码库默认行为基线(php think run)", + "author_only": false + }, + "docker-serve": { + "description": "Docker 部署模式(基于基础镜像,nginx+php-fpm)", "author_only": false }, "full": {