-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathdeploy.php
More file actions
119 lines (100 loc) · 3.05 KB
/
deploy.php
File metadata and controls
119 lines (100 loc) · 3.05 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
<?php
/**
* GitHub Webhook Deploy Handler
*
* Automatically deploys tagged releases.
*
* @package BodyRefactoring
*/
// Load dependencies and helpers.
require_once __DIR__ . '/tools.php';
// Configuration from .env
define( 'WEBHOOK_SECRET', getenv( 'DEPLOY_SECRET' ) );
define( 'REPO_PATH', getenv( 'REPO_PATH' ) );
define( 'LOG_FILE', REPO_PATH . '/deploy.log' );
/**
* Log a message to the deployment log file.
*
* @param string $message The message to log.
*/
function log_message( string $message ): void {
$timestamp = date( 'Y-m-d H:i:s' );
$log_entry = "[$timestamp] $message\n";
file_put_contents( LOG_FILE, $log_entry, FILE_APPEND );
}
// Verify webhook signature
$headers = getallheaders();
$signature = $headers['X-Hub-Signature-256'] ?? '';
if ( empty( $signature ) ) {
http_response_code( 403 );
log_message( 'ERROR: No signature provided' );
die( 'Forbidden: No signature' );
}
// Validate payload
$payload = file_get_contents( 'php://input' );
$expected_hash = 'sha256=' . hash_hmac( 'sha256', $payload, WEBHOOK_SECRET );
if ( ! hash_equals( $expected_hash, $signature ) ) {
http_response_code( 403 );
log_message( 'ERROR: Invalid signature' );
die( 'Forbidden: Invalid signature' );
}
// Parse payload
$data = json_decode( $payload, true );
if ( ! $data ) {
http_response_code( 400 );
log_message( 'ERROR: Invalid JSON payload' );
die( 'Bad Request: Invalid JSON' );
}
// Only respond to tag pushes (releases)
$ref = $data['ref'] ?? '';
if ( strpos( $ref, 'refs/tags/' ) !== 0 ) {
log_message( 'INFO: Ignored push to ref: ' . $ref );
http_response_code( 200 );
echo json_encode(
[
'status' => 'ignored',
'message' => 'Not a tag push',
]
);
exit;
}
// Extract tag name
$tag = str_replace( 'refs/tags/', '', $ref );
// Log deployment start
$pusher = $data['pusher']['name'] ?? 'unknown';
log_message( "INFO: Deployment started by {$pusher} for tag: {$tag}" );
// Execute git commands to deploy tag
chdir( REPO_PATH );
// Fetch all tags
exec( 'git fetch --tags 2>&1', $fetch_output, $fetch_code );
log_message( 'INFO: Git fetch tags - ' . implode( ' ', $fetch_output ) );
// Checkout the specific tag (discard local changes)
exec( "git checkout --force {$tag} 2>&1", $checkout_output, $checkout_code );
log_message( 'INFO: Git checkout tag - ' . implode( ' ', $checkout_output ) );
// Combine all output
$output = array_merge( $fetch_output, $checkout_output );
$return_code = max( $fetch_code, $checkout_code );
if ( $return_code === 0 ) {
log_message( "SUCCESS: Deployment completed successfully for tag: {$tag}" );
log_message( 'OUTPUT: ' . implode( "\n", $output ) );
http_response_code( 200 );
echo json_encode(
[
'status' => 'success',
'message' => 'Deployment successful',
'tag' => $tag,
]
);
} else {
log_message( "ERROR: Deployment failed for tag: {$tag} with code {$return_code}" );
log_message( 'OUTPUT: ' . implode( "\n", $output ) );
http_response_code( 500 );
echo json_encode(
[
'status' => 'error',
'message' => 'Deployment failed',
'tag' => $tag,
'output' => $output,
]
);
}