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