-
Notifications
You must be signed in to change notification settings - Fork 4
178 lines (150 loc) · 6.19 KB
/
Copy pathdeploy.yml
File metadata and controls
178 lines (150 loc) · 6.19 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
name: Deploy
on:
workflow_dispatch:
inputs:
environment:
description: "Target deployment environment"
required: true
type: choice
options:
- staging
- production
default: staging
skip_tests:
description: "Skip tests before deploying (not recommended)"
required: false
type: boolean
default: false
jobs:
# ──────────────────────────────────────────────
# Job 1 – Full Test Suite
# ──────────────────────────────────────────────
test:
name: "Test Suite (PHP 8.3)"
runs-on: ubuntu-latest
if: ${{ !inputs.skip_tests }}
steps:
- name: Checkout code
uses: actions/checkout@v7
- name: Set up PHP 8.3
uses: shivammathur/setup-php@v2
with:
php-version: "8.3"
extensions: pdo, pdo_sqlite, mbstring, xml
coverage: none
- name: Cache Composer dependencies
uses: actions/cache@v6
with:
path: vendor
key: composer-deploy-${{ hashFiles('composer.lock') }}
restore-keys: composer-deploy-
- name: Install Composer dependencies (with dev)
run: composer install --no-progress --prefer-dist --no-interaction
- name: Run syntax check
run: find src/ public/ -name "*.php" -print0 | xargs -0 -n1 php -l
- name: Run PHPUnit tests
run: vendor/bin/phpunit --colors=always
# ──────────────────────────────────────────────
# Job 2 – Production Build
# ──────────────────────────────────────────────
build:
name: "Build (production)"
runs-on: ubuntu-latest
needs: test
# Always run build: even when tests were skipped
if: always() && (needs.test.result == 'success' || needs.test.result == 'skipped')
steps:
- name: Checkout code
uses: actions/checkout@v7
- name: Set up PHP 8.3
uses: shivammathur/setup-php@v2
with:
php-version: "8.3"
extensions: pdo, mbstring, xml
coverage: none
- name: Install production Composer dependencies only
run: |
composer install \
--no-dev \
--optimize-autoloader \
--classmap-authoritative \
--no-progress \
--prefer-dist \
--no-interaction
- name: Create .env from example (CI placeholder)
run: cp .env.example .env
- name: Verify autoloader integrity
run: php -r "require 'vendor/autoload.php'; echo 'Autoloader OK' . PHP_EOL;"
- name: Package release artifact
run: |
mkdir -p dist
zip -r dist/release-${{ github.sha }}.zip \
public/ src/ vendor/ .env.example composer.json \
--exclude "*.git*"
echo "📦 Build artifact: dist/release-${{ github.sha }}.zip"
ls -lh dist/
- name: Upload release artifact
uses: actions/upload-artifact@v4
with:
name: release-${{ github.sha }}
path: dist/release-${{ github.sha }}.zip
retention-days: 7
# ──────────────────────────────────────────────
# Job 3 – Deploy
# ──────────────────────────────────────────────
deploy:
name: "Deploy → ${{ inputs.environment }}"
runs-on: ubuntu-latest
needs: build
environment: ${{ inputs.environment }}
steps:
- name: Checkout code
uses: actions/checkout@v7
- name: Download release artifact
uses: actions/download-artifact@v4
with:
name: release-${{ github.sha }}
path: dist/
- name: Copy artifact to server via SCP
uses: appleboy/scp-action@v1
with:
host: ${{ secrets.SSH_HOST }}
username: ${{ secrets.SSH_USER }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
port: ${{ secrets.SSH_PORT || '22' }}
source: "dist/release-${{ github.sha }}.zip"
target: "/tmp/"
- name: Extract and deploy via SSH
uses: appleboy/ssh-action@v1
env:
DEPLOY_PATH: ${{ secrets.DEPLOY_PATH }}
SHA: ${{ github.sha }}
with:
host: ${{ secrets.SSH_HOST }}
username: ${{ secrets.SSH_USER }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
port: ${{ secrets.SSH_PORT || '22' }}
envs: DEPLOY_PATH,SHA
script: |
# 1. Create releases and shared directories if they don't exist
mkdir -p $DEPLOY_PATH/releases
mkdir -p $DEPLOY_PATH/shared
# 2. Extract artifact into a new release folder
mkdir -p $DEPLOY_PATH/releases/$SHA
unzip -q /tmp/dist/release-$SHA.zip -d $DEPLOY_PATH/releases/$SHA
# 3. Ensure shared .env exists, then link it
touch $DEPLOY_PATH/shared/.env
ln -sf $DEPLOY_PATH/shared/.env $DEPLOY_PATH/releases/$SHA/.env
# 4. Swap the "current" symlink for zero-downtime deployment
ln -sfn $DEPLOY_PATH/releases/$SHA $DEPLOY_PATH/current
# 5. Clean up the temp zip file
rm -f /tmp/dist/release-$SHA.zip
# 6. Keep only the last 5 releases (cleanup)
ls -dt $DEPLOY_PATH/releases/* | tail -n +6 | xargs -d '\n' rm -rf -- || true
echo "✅ Successfully deployed $SHA to $DEPLOY_PATH/current"
- name: Post-deploy smoke test (stub)
run: |
echo "🔍 Running smoke test against ${{ inputs.environment }}..."
echo "👉 Add curl/http check against your deployed URL here:"
echo ' curl -sf https://your-domain.com/ | grep "Welcome to Basic PHP RESTful API"'
echo "✅ Smoke test stub passed."