-
Notifications
You must be signed in to change notification settings - Fork 2
/
gitlab-autodeploy-v2.php
182 lines (152 loc) · 5.11 KB
/
gitlab-autodeploy-v2.php
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
179
180
181
182
<?php
/*
* GitLab AutoDeploy V2
* https://afaan.ml/gitlab-autodeploy
*
* Automatically deploy your web app repositories on "git push" or any other hook.
* New in V2:
* - Complete rewrite
* - Only fetch and deploy changes instead of complete redeployment
*
* Author: Afaan Bilal
* Author URL: https://google.com/+AfaanBilal
*
* - No Shell Access Required
* - Best for Shared Hosting Platforms
* - Public, internal and private repositories supported
*
* (c) 2016 Afaan Bilal
*
*/
// Repo ID
define('REPO_ID', 0);
// Private Token
define('PRIVATE_TOKEN', '[PRIVATE-TOKEN]');
// Deploy Directory
// (RELATIVE TO THIS FILE)
// Set to empty string in case of current directory.
// If not empty, then MUST end with a forward-slash
define('DEPLOY_DIR', '');
// Branch name
define('BRANCH', 'master');
// Logging
//
// if you don't want logging, just set to FALSE
// else set a filename or leave as is.
define('LOGFILE', 'gitlab-autodeploy-v2.log');
// TimeZone (for Logging)
date_default_timezone_set("Asia/Kolkata");
// The GitLab API endpoint for project repositories
define('API_ENDPOINT', 'https://gitlab.com/api/v3/projects/' . REPO_ID . '/repository');
// API URL for comparing two commits
//
// We need the 'diffs' part of the response
// to check what files have changed
define('API_COMPARE', API_ENDPOINT . '/compare?private_token=' . PRIVATE_TOKEN);
// API URL for getting file data
define('API_FILES', API_ENDPOINT . '/files?private_token=' . PRIVATE_TOKEN . '&ref=' . BRANCH . '&file_path=');
// Logging
function writeLog($data)
{
if (LOGFILE == FALSE)
return;
if (!file_exists(LOGFILE))
{
$logFile = fopen(LOGFILE, "a+");
fwrite($logFile, "--------------------------------------------------------\n");
fwrite($logFile, "| PHP GitLab AUTO-DEPLOY V2 |\n");
fwrite($logFile, "| https://afaan.ml/gitlab-autodeploy |\n");
fwrite($logFile, "| (c) Afaan Bilal ( https://afaan.ml ) |\n");
fwrite($logFile, "--------------------------------------------------------\n");
fwrite($logFile, "\n\n");
fclose($logFile);
}
$fh = fopen(LOGFILE, "a+");
fwrite($fh, "\nTimestamp: ".date("d-m-Y h:i:s a"));
fwrite($fh, "\n\n {$data}");
fwrite($fh, "\n\n");
fclose($fh);
}
// delete files
//
// delete the file and if the containing
// folder is empty, remove it as well.
function deleteFile($path)
{
@unlink($path);
$dir = dirname($path);
// if the folder is empty now, delete it as well
if (count(glob("{$dir}/*")) === 0)
rmdir($dir);
}
// send some response to the GitLab server
// GitLab doesn't care what we send
// but just to be nice :)
echo "{status:success}";
// get the webhook data send by GitLab
$json = file_get_contents('php://input');
$data = json_decode($json, TRUE);
// send compare request
//
// $data['before'] contains the starting commit sha1 of the push and
// $data['after'] contains the ending commit sha1 of the push
// so we just compare the two to see what has changed
$compareData = json_decode(file_get_contents(API_COMPARE . '&from=' . $data['before'] . '&to=' . $data['after']), TRUE);
// if there is an error, log it and exit
if (in_array("message", array_keys($compareData)))
{
writeLog("Error: ".$compareData['message']);
exit;
}
// get file data
$filesRealData = [];
foreach ($compareData['diffs'] as $v)
{
// Log every changed file
writeLog(
" == FileChanged == \r\n".
"Path: {$v['old_path']} => {$v['new_path']}\r\n".
"New: {$v['new_file']}\r\n".
"Renamed: {$v['renamed_file']}\r\n".
"Deleted: {$v['deleted_file']}\r\n".
" == =========== =="
);
if ($v['deleted_file'])
{
// the file has been deleted in the repo
// so just delete it here as well and continue
// we don't need to do anything else with it
deleteFile($v['old_path']);
continue;
}
else if ($v['renamed_file'])
{
// the file has been renamed in the repo
// so just delete the old named file
// and treat the renamed one as a new file
deleteFile($v['old_path']);
}
// get the actual file data
$fileData = json_decode(file_get_contents(API_FILES . urlencode($v['new_path'])), TRUE);
// if there is an error, log it and continue
if (in_array("message", array_keys($fileData)))
{
writeLog("Error: ".$fileData['message']);
continue;
}
// collect the files to be written to disk
// and decode the content (it's base64 encoded)
$filesRealData[] = [
'path' => $fileData['file_path'],
'content' => base64_decode($fileData['content'])
];
}
// write files to disk
foreach ($filesRealData as $v)
{
if (!file_exists(DEPLOY_DIR . dirname($v['path'])))
mkdir(dirname($v['path']), 0777, TRUE);
file_put_contents(DEPLOY_DIR . $v['path'], $v['content']);
}
// and we are done!
writeLog("Deployment complete.");