5 Commits
Author SHA1 Message Date
goukiandCursor b5979462f0 fix: ensure shared .env is readable by PHP before config:cache
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-18 15:14:18 +08:00
goukiandCursor c726bfdbd7 fix: avoid host chown after composer; prune releases in container only
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-18 15:09:02 +08:00
goukiandCursor c0579c502f fix: prune old releases via php container to avoid permission denied
composer-created vendor trees are not deletable by the host runner user

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-18 15:04:27 +08:00
goukiandCursor c412331154 fix: 加固生产部署权限与测试网络
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-16 12:57:24 +08:00
goukiandCursor 37c5e1f0d8 test: 仅运行后端 HTTP API 测试
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-15 21:53:13 +08:00
4 changed files with 29 additions and 6 deletions
+6
View File
@@ -1,5 +1,11 @@
# Changelog # Changelog
## 1.0.2 - 2026-07-15
- Use the service hostname for isolated MySQL API tests.
- Add group-writable release permissions for the 1Panel PHP runtime user.
- Pin consuming workflows to immutable toolkit release tags.
## 1.0.0 - 2026-07-15 ## 1.0.0 - 2026-07-15
- Add a path-filtered Laravel verification and 1Panel deployment workflow. - Add a path-filtered Laravel verification and 1Panel deployment workflow.
+18 -1
View File
@@ -20,6 +20,7 @@ done
release_id="${RELEASE_ID:-$(date -u +%Y%m%d%H%M%S)}" release_id="${RELEASE_ID:-$(date -u +%Y%m%d%H%M%S)}"
keep_releases="${KEEP_RELEASES:-5}" keep_releases="${KEEP_RELEASES:-5}"
php_user="${PHP_RUNTIME_USER:-1000:1000}" php_user="${PHP_RUNTIME_USER:-1000:1000}"
php_group="${PHP_RUNTIME_GROUP:-1000}"
dry_run="${DRY_RUN:-false}" dry_run="${DRY_RUN:-false}"
host_release="$DEPLOY_ROOT/releases/$release_id" host_release="$DEPLOY_ROOT/releases/$release_id"
container_release="$CONTAINER_DEPLOY_ROOT/releases/$release_id" container_release="$CONTAINER_DEPLOY_ROOT/releases/$release_id"
@@ -104,12 +105,23 @@ run rsync -a --delete \
--exclude='storage' \ --exclude='storage' \
--exclude='vendor' \ --exclude='vendor' \
"$SOURCE_DIR/" "$host_release/" "$SOURCE_DIR/" "$host_release/"
run chgrp -R "$php_group" "$host_release"
run chmod -R g+rwX "$host_release"
run ln -s ../../shared/.env "$host_release/.env" run ln -s ../../shared/.env "$host_release/.env"
run ln -s ../../shared/storage "$host_release/storage" run ln -s ../../shared/storage "$host_release/storage"
# PHP runs as uid/gid 1000 inside the container. act_runner often owns
# shared/.env as 0600, which makes env() empty and config:cache write NULLs.
run chgrp "$php_group" "$DEPLOY_ROOT/shared/.env"
run chmod 640 "$DEPLOY_ROOT/shared/.env"
run docker exec --user "$php_user" --workdir "$container_release" \ run docker exec --user "$php_user" --workdir "$container_release" \
"$PHP_CONTAINER" composer install \ "$PHP_CONTAINER" composer install \
--no-dev --no-interaction --prefer-dist --optimize-autoloader --no-dev --no-interaction --prefer-dist --optimize-autoloader
# Keep the release readable by the PHP runtime group. Do not chown on the host:
# act_runner cannot change ownership of files created inside the container.
run docker exec "$PHP_CONTAINER" sh -c \
"chown -R ${php_user} '${container_release}' && chmod -R g+rwX '${container_release}'"
if test "$dry_run" != "true"; then if test "$dry_run" != "true"; then
bash -c "$BACKUP_COMMAND" bash -c "$BACKUP_COMMAND"
@@ -143,7 +155,12 @@ if test "$dry_run" != "true"; then
' '
) )
if test "${#old_releases[@]}" -gt 0; then if test "${#old_releases[@]}" -gt 0; then
rm -rf -- "${old_releases[@]}" for old_release in "${old_releases[@]}"; do
release_name="$(basename "$old_release")"
# Delete via the PHP container as root so vendor trees are removable.
run docker exec "$PHP_CONTAINER" \
rm -rf "$CONTAINER_DEPLOY_ROOT/releases/$release_name"
done
fi fi
fi fi
+4 -4
View File
@@ -12,14 +12,14 @@ on:
jobs: jobs:
verify: verify:
runs-on: ubuntu-latest runs-on: ubuntu-latest
env:
DB_HOST: mysql
services: services:
mysql: mysql:
image: mysql:8.0 image: mysql:8.0
env: env:
MYSQL_ALLOW_EMPTY_PASSWORD: "yes" MYSQL_ALLOW_EMPTY_PASSWORD: "yes"
MYSQL_DATABASE: new_pet_test MYSQL_DATABASE: new_pet_test
ports:
- 3306:3306
options: >- options: >-
--health-cmd="mysqladmin ping" --health-cmd="mysqladmin ping"
--health-interval=10s --health-interval=10s
@@ -50,7 +50,7 @@ jobs:
php artisan key:generate --env=testing php artisan key:generate --env=testing
- name: Run HTTP API tests - name: Run HTTP API tests
working-directory: server working-directory: server
run: php artisan test run: php artisan test tests/Feature/ApiFlowTest.php
- name: Build server assets - name: Build server assets
working-directory: server working-directory: server
run: npm run build run: npm run build
@@ -69,7 +69,7 @@ jobs:
with: with:
name: server-build name: server-build
path: server/public/build path: server/public/build
- uses: https://gitea.neatcn.com/pets/deployment-toolkit/actions/laravel-release@v1 - uses: https://gitea.neatcn.com/pets/deployment-toolkit/actions/laravel-release@v1.0.2
with: with:
source-dir: server source-dir: server
deploy-root: ${{ vars.SERVER_DEPLOY_ROOT }} deploy-root: ${{ vars.SERVER_DEPLOY_ROOT }}
+1 -1
View File
@@ -42,7 +42,7 @@ jobs:
test -n "$WECHAT_CI_PRIVATE_KEY" test -n "$WECHAT_CI_PRIVATE_KEY"
umask 077 umask 077
printf '%s' "$WECHAT_CI_PRIVATE_KEY" > "$RUNNER_TEMP/wechat-ci.key" printf '%s' "$WECHAT_CI_PRIVATE_KEY" > "$RUNNER_TEMP/wechat-ci.key"
- uses: https://gitea.neatcn.com/pets/deployment-toolkit/actions/wechat-preview@v1 - uses: https://gitea.neatcn.com/pets/deployment-toolkit/actions/wechat-preview@v1.0.2
with: with:
project-path: miniapp project-path: miniapp
appid: ${{ vars.MINIAPP_APPID }} appid: ${{ vars.MINIAPP_APPID }}