Skip to content

Commit 177b191

Browse files
committed
Update deployment files to include OpCache reset and ssm environment management
1 parent 8f4a6a0 commit 177b191

7 files changed

Lines changed: 194 additions & 115 deletions

File tree

.github/workflows/deploy.yml

Lines changed: 55 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,17 @@ on:
2222
- development # Development environment
2323
release:
2424
types: [published] # Production deployment trigger
25+
26+
permissions:
27+
id-token: write
28+
contents: read
29+
2530
jobs:
2631
# Create release when pushing to main
2732
create-release:
2833
runs-on: ubuntu-latest
34+
permissions:
35+
contents: write
2936
if: "github.ref == 'refs/heads/main' && !contains(github.event.head_commit.message, '[skip deploy]') && !contains(github.event.head_commit.message, '[no deploy]')"
3037
outputs:
3138
release-tag: ${{ steps.create_release.outputs.tag_name }}
@@ -89,8 +96,9 @@ jobs:
8996
MINOR=${BASH_REMATCH[2]}
9097
PATCH=${BASH_REMATCH[3]}
9198
else
92-
echo "Error: Could not parse version $CURRENT"
93-
exit 1
99+
MAJOR=0
100+
MINOR=0
101+
PATCH=0
94102
fi
95103
96104
# Increment based on bump type
@@ -162,17 +170,18 @@ jobs:
162170
- name: Get Runner IP
163171
id: ip
164172
uses: haythem/public-ip@v1.3
173+
- name: Configure AWS Credentials
174+
uses: aws-actions/configure-aws-credentials@v4
175+
with:
176+
role-to-assume: arn:aws:iam::147899039648:role/GitHubActionsDeployRole
177+
aws-region: ${{ secrets.AWS_REGION }}
165178
- name: Whitelist Runner IP in AWS Security Group
166179
run: |
167180
aws ec2 authorize-security-group-ingress \
168181
--group-id ${{ secrets.AWS_SECURITY_GROUP_ID }} \
169182
--protocol tcp \
170183
--port 22 \
171184
--cidr ${{ steps.ip.outputs.ipv4 }}/32
172-
env:
173-
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
174-
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
175-
AWS_DEFAULT_REGION: ${{ secrets.AWS_REGION }}
176185
- name: Setup PHP
177186
uses: shivammathur/setup-php@v2
178187
with:
@@ -205,9 +214,23 @@ jobs:
205214
run: npm run production
206215
- name: Create deployment package
207216
run: |
208-
mkdir -p deployment-package
209-
rsync -av --exclude=node_modules --exclude=.git --exclude=.github --exclude=tests --exclude=storage/logs --exclude=vendor . deployment-package/
210-
cp -r public/css public/js public/fonts public/images public/svg public/mix-manifest.json deployment-package/public/ || true
217+
# Clean any prior
218+
rm -rf deployment-package || true
219+
# Create isolated temp dir
220+
TEMP_DIR=$(mktemp -d)
221+
# Sync repo files to temp
222+
rsync -av \
223+
--exclude=node_modules \
224+
--exclude=.git \
225+
--exclude=.github \
226+
--exclude=tests \
227+
--exclude=storage/logs \
228+
--exclude=vendor \
229+
. "$TEMP_DIR/"
230+
# Copy assets into temp/public/
231+
cp -r public/css public/js public/fonts public/images public/svg public/mix-manifest.json "$TEMP_DIR/public/" || true
232+
# Move to package name
233+
mv "$TEMP_DIR" deployment-package
211234
- name: Upload deployment artifact
212235
uses: actions/upload-artifact@v4
213236
with:
@@ -232,10 +255,6 @@ jobs:
232255
--protocol tcp \
233256
--port 22 \
234257
--cidr ${{ steps.ip.outputs.ipv4 }}/32
235-
env:
236-
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
237-
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
238-
AWS_DEFAULT_REGION: ${{ secrets.AWS_REGION }}
239258
240259
build-and-deploy-development:
241260
runs-on: ubuntu-latest
@@ -247,17 +266,18 @@ jobs:
247266
- name: Get Runner IP
248267
id: ip
249268
uses: haythem/public-ip@v1.3
269+
- name: Configure AWS Credentials
270+
uses: aws-actions/configure-aws-credentials@v4
271+
with:
272+
role-to-assume: arn:aws:iam::147899039648:role/GitHubActionsDeployRole
273+
aws-region: ${{ secrets.AWS_REGION }}
250274
- name: Whitelist Runner IP in AWS Security Group
251275
run: |
252276
aws ec2 authorize-security-group-ingress \
253277
--group-id ${{ secrets.AWS_SECURITY_GROUP_ID }} \
254278
--protocol tcp \
255279
--port 22 \
256280
--cidr ${{ steps.ip.outputs.ipv4 }}/32
257-
env:
258-
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
259-
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
260-
AWS_DEFAULT_REGION: ${{ secrets.AWS_REGION }}
261281
- name: Setup PHP
262282
uses: shivammathur/setup-php@v2
263283
with:
@@ -290,9 +310,23 @@ jobs:
290310
run: npm run production
291311
- name: Create deployment package
292312
run: |
293-
mkdir -p deployment-package
294-
rsync -av --exclude=node_modules --exclude=.git --exclude=.github --exclude=tests --exclude=storage/logs --exclude=vendor . deployment-package/
295-
cp -r public/css public/js public/fonts public/images public/svg public/mix-manifest.json deployment-package/public/ || true
313+
# Clean any prior
314+
rm -rf deployment-package || true
315+
# Create isolated temp dir
316+
TEMP_DIR=$(mktemp -d)
317+
# Sync repo files to temp
318+
rsync -av \
319+
--exclude=node_modules \
320+
--exclude=.git \
321+
--exclude=.github \
322+
--exclude=tests \
323+
--exclude=storage/logs \
324+
--exclude=vendor \
325+
. "$TEMP_DIR/"
326+
# Copy assets into temp/public/
327+
cp -r public/css public/js public/fonts public/images public/svg public/mix-manifest.json "$TEMP_DIR/public/" || true
328+
# Move to package name
329+
mv "$TEMP_DIR" deployment-package
296330
- name: Upload deployment artifact
297331
uses: actions/upload-artifact@v4
298332
with:
@@ -315,8 +349,4 @@ jobs:
315349
--group-id ${{ secrets.AWS_SECURITY_GROUP_ID }} \
316350
--protocol tcp \
317351
--port 22 \
318-
--cidr ${{ steps.ip.outputs.ipv4 }}/32
319-
env:
320-
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
321-
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
322-
AWS_DEFAULT_REGION: ${{ secrets.AWS_REGION }}
352+
--cidr ${{ steps.ip.outputs.ipv4 }}/32

app/Http/Controllers/HomeController.php

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,9 @@
2121
namespace App\Http\Controllers;
2222

2323
use Illuminate\Contracts\Support\Renderable;
24+
use Illuminate\Http\Request;
25+
use Illuminate\Support\Facades\Response;
2426

25-
/**
26-
* Controller for handling home page functionality.
27-
*
28-
* This controller is responsible for rendering the main home page
29-
* of the application.
30-
*/
3127
class HomeController extends Controller
3228
{
3329
/**
@@ -39,4 +35,27 @@ public function index(): Renderable
3935
{
4036
return view('home');
4137
}
38+
39+
/**
40+
* Reset the PHP OpCache.
41+
*/
42+
public function resetOpCache(Request $request)
43+
{
44+
$token = $request->input('token');
45+
$validToken = config('app.opcache_webhook_token');
46+
47+
if (empty($validToken) || $token !== $validToken) {
48+
return Response::json(['message' => 'Unauthorized'], 403);
49+
}
50+
51+
if (function_exists('opcache_reset')) {
52+
if (opcache_reset()) {
53+
return Response::json(['message' => 'OpCache reset successful'], 200);
54+
}
55+
56+
return Response::json(['message' => 'OpCache reset failed'], 500);
57+
}
58+
59+
return Response::json(['message' => 'OpCache not available'], 500);
60+
}
4261
}

bootstrap/app.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@
2020
'cacheResponse' => \Spatie\ResponseCache\Middlewares\CacheResponse::class,
2121
'doNotCacheResponse' => \Spatie\ResponseCache\Middlewares\DoNotCacheResponse::class,
2222
]);
23+
24+
$middleware->validateCsrfTokens(except: [
25+
'/opcache/reset',
26+
]);
2327
})
2428
->withExceptions(function (Exceptions $exceptions) {
2529
//

config/app.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@
5757
'path' => base_path(),
5858
'tag' => env('APP_TAG'),
5959
'server_user' => env('APP_SERVER_USER'),
60+
'opcache_webhook_token' => env('OPCACHE_WEBHOOK_TOKEN'),
6061

6162
/*
6263
|--------------------------------------------------------------------------

deploy.php

Lines changed: 38 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,10 @@
4242
set('php_fpm_version', '8.3');
4343
set('ssh_multiplexing', true);
4444
set('writable_mode', 'chmod');
45-
set('keep_releases', 5); // Keep only 3 recent releases
45+
set('keep_releases', 3); // Keep only 3 recent releases
46+
47+
// Use sudo for cleanup to prevent "Directory not empty" or permission errors
48+
set('cleanup_use_sudo', true);
4649

4750
// Shared Files (persisted across deployments)
4851
set('shared_files', [
@@ -64,22 +67,37 @@
6467
// Files/Directories to Remove After Deployment
6568
set('clear_paths', [
6669
'node_modules', // Remove after CI artifacts are deployed
70+
'deployment-package', // Remove any residual nesting dirs
6771
]);
6872

73+
// Determine if the local identity file exists (for manual deployments)
74+
$localKey = '/home/ubuntu/.ssh/biospexaws.pem';
75+
$hasLocalKey = file_exists($localKey);
76+
6977
// Server Configurations
7078
// Production
7179
host('production')
7280
->set('hostname', '3.142.169.134')
7381
->set('deploy_path', '{{base_path}}/digitizationacademy')
7482
->set('branch', 'main')
75-
->set('environment', 'production');
83+
->set('environment', 'production')
84+
->set('app_tag', 'digacad');
85+
86+
if ($hasLocalKey) {
87+
host('production')->set('identity_file', $localKey);
88+
}
7689

7790
// Development
7891
host('development')
7992
->set('hostname', '3.138.217.206')
8093
->set('deploy_path', '{{base_path}}/digitizationacademy')
8194
->set('branch', 'development')
82-
->set('environment', 'development');
95+
->set('environment', 'development')
96+
->set('app_tag', 'digacad');
97+
98+
if ($hasLocalKey) {
99+
host('development')->set('identity_file', $localKey);
100+
}
83101

84102
/*
85103
* DEPLOYMENT TASK SEQUENCE - CI/CD Implementation
@@ -91,18 +109,20 @@
91109
task('deploy', [
92110
// Phase 1: Preparation
93111
'deploy:prepare', // Create release directory and setup structure
94-
'clear:package-cache', // Clear package cache BEFORE composer operations
112+
113+
// Phase 1.5: Ensure .env from SSM is ready
114+
'env:ssm',
95115

96116
// Phase 2: Dependencies & Assets
97-
'deploy:vendors', // Use default Laravel recipe (now works with ext-intl)
98-
'deploy:ci-artifacts', // Download & extract pre-built assets from GitHub Actions
117+
'deploy:vendors', // Install PHP Composer dependencies safely
118+
'deploy:ci-artifacts', // Download & extract pre-built assets from GitHub Actions
99119

100120
// Phase 3: Laravel Setup
101121
'artisan:storage:link', // Create symbolic link for storage directory
122+
'artisan:package:discover', // Run package discovery
102123
'artisan:horizon:publish', // Publish Laravel Horizon assets
103124
'artisan:sweetalert:publish', // Publish Sweet Alert assets
104125
'artisan:filament:assets',
105-
'artisan:filament:optimize', // Optimize Filament resources and assets
106126
'artisan:app:deploy-files', // Custom app deployment files
107127

108128
// Phase 4: Database & Updates
@@ -117,18 +137,22 @@
117137
'artisan:view:cache', // Cache Blade templates
118138
'artisan:event:cache', // Cache event listeners
119139
'artisan:optimize', // Run Laravel optimization
140+
'artisan:filament:optimize', // Optimize Filament resources and assets
120141

121-
// Phase 6: OpCache Management
122-
'opcache:reset',
123-
124-
// Phase 7: Domain-Specific Supervisor Management and Horizon
125-
'supervisor:reload', // Update configs only
142+
// Phase 7: Domain-Specific Supervisor Management
143+
'supervisor:reload', // Update configs only
126144
'artisan:horizon:terminate',
145+
'artisan:queue:restart',
127146

128147
// Phase 8: Finalization
129-
'set:permissions', // Set proper file permissions
148+
'set:permissions',
130149
'deploy:clear_paths', // Remove unnecessary files/directories
131-
'deploy:publish', // Switch to new release (atomic deployment)
150+
'deploy:publish', // <--- SYMLINK SWITCHES HERE
151+
152+
// Phase 6: OpCache Management (Now moved after publish)
153+
'opcache:reset', // <--- NOW IT WILL FIND THE ROUTE
154+
155+
'deploy:verify-structure', // Verify flat structure post-deploy
132156
]);
133157

134158
// Hooks

0 commit comments

Comments
 (0)