Skip to content

Commit 583f17e

Browse files
committed
Initial drop.
0 parents  commit 583f17e

9 files changed

+414
-0
lines changed

.gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
/vendor/
2+
config.json

LICENSE

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
Copyright (c) 2013 Dragonfly Development Inc.
2+
3+
Permission is hereby granted, free of charge, to any person obtaining a copy
4+
of this software and associated documentation files (the "Software"), to deal
5+
in the Software without restriction, including without limitation the rights
6+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7+
copies of the Software, and to permit persons to whom the Software is furnished
8+
to do so, subject to the following conditions:
9+
10+
The above copyright notice and this permission notice shall be included in all
11+
copies or substantial portions of the Software.
12+
13+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19+
THE SOFTWARE.

README.md

+157
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
Git Subsplit GitHub WebHook
2+
===========================
3+
4+
[GitHub][1] WebHook for Git subsplits managed by [dflydev-git-subsplit][2].
5+
6+
Automates the process of keeping one-way read-only subtree splits up to date
7+
with the source repository.
8+
9+
10+
Usage
11+
-----
12+
13+
### Installation
14+
15+
#### If You Already Have Composer
16+
17+
composer create-project dflydev/git-subsplit-github-webhook:1.0.* \
18+
--prefer-dist -n -s dev webhook
19+
cd webhook
20+
21+
#### If You Need Composer
22+
23+
curl -s https://getcomposer.org/installer | php
24+
php composer.phar create-project dflydev/git-subsplit-github-webhook:1.0.* \
25+
--prefer-dist -n -s dev webhook
26+
cd webhook
27+
28+
### Redis
29+
30+
Ensure that the Redis server is running.
31+
32+
### Configure
33+
34+
Copy `config.json.dist` to `config.json` and edit it accordingly. Please make sure
35+
to pay special attention to setting `working-directory` correctly.
36+
37+
### Web Server
38+
39+
Setup a virtual host pointing to `web/` as its docroot. Assuming the virtual host
40+
is **webhook.example.com**, test the WebHook by visiting the following URL:
41+
**http://webhook.example.com/subsplit-webhook.php**
42+
43+
### Worker
44+
45+
Start the worker by running `php bin/subsplit-worker.php`.
46+
47+
### GitHub
48+
49+
From your repository go to **Settings** / **Service Hooks** / **WebHook URLs**.
50+
Enter the URL to your WebHook and click **Update Settings**.
51+
52+
Click **WebHook URLs** again and click **Test Hook**.
53+
54+
If everything is setup correctly the Worker should give you some sort of feedback.
55+
56+
57+
Configuration
58+
-------------
59+
60+
### Example
61+
62+
```
63+
{
64+
"working-directory": "/home/myuser/.git-subsplit-working",
65+
"allowed-ips": ["127.0.0.1"],
66+
"projects": {
67+
"sculpin": {
68+
"url": "https://github.com/sculpin/sculpin",
69+
"repository-url": "[email protected]:sculpin/sculpin.git",
70+
"splits": [
71+
"src/Sculpin/Core:[email protected]:sculpin/core.git"
72+
]
73+
},
74+
"react": {
75+
"url": "https://github.com/reactphp/react",
76+
"splits": [
77+
"src/React/EventLoop:[email protected]:reactphp/event-loop.git",
78+
"src/React/Stream:[email protected]:reactphp/stream.git",
79+
"src/React/Cache:[email protected]:reactphp/cache.git",
80+
"src/React/Socket:[email protected]:reactphp/socket.git",
81+
"src/React/Http:[email protected]:reactphp/http.git",
82+
"src/React/HttpClient:[email protected]:reactphp/http-client.git",
83+
"src/React/Dns:[email protected]:reactphp/dns.git"
84+
]
85+
}
86+
}
87+
}
88+
```
89+
90+
### Schema
91+
92+
#### working-directory
93+
94+
*String. Default: None. **Required.***
95+
96+
The directory in which the subsplits will be processed. This is more or less
97+
a temporary directory in which all projects will have their subsplit initialized.
98+
99+
#### allowed-ips
100+
101+
*Array. Default: ['207.97.227.253', '50.57.128.197', '108.171.174.178']*
102+
103+
The IP addresses that are allowed to call the WebHook. The default values are
104+
GitHub's IP addresses published here.
105+
106+
#### projects
107+
108+
*Object. **Required**.*
109+
110+
An object whose keys are project names and values are a project description
111+
object.
112+
113+
Project names should only contain a-z, A-Z, 0-9, `.`, `_`, and `-`.
114+
115+
Each project description object can have the following properties:
116+
117+
* **url**:
118+
The URL for the project. The WebHook will check each incoming request's
119+
`url` property against each project's listed `url` property to determine
120+
which project the request is for.
121+
122+
This URL will look like: **https://github.com/sculpin/sculpin**
123+
124+
Note: The URL is secure (http**s**) and does not contain `.git` extension.
125+
* **repository-url**:
126+
The URL that `git` will use to check out the project. This setting is
127+
optional. If it is not defined the repository URL will be read from the
128+
incoming request.
129+
* **splits**:
130+
An array of subsplit definitions as defined by [dflydev-git-subsplit][2].
131+
The pattern for the splits is `${subPath}:${url}`.
132+
133+
134+
License
135+
-------
136+
137+
MIT, see LICENSE.
138+
139+
140+
Community
141+
---------
142+
143+
If you have questions or want to help out, join us in the
144+
**#dflydev** channel on irc.freenode.net.
145+
146+
147+
Not Invented Here
148+
-----------------
149+
150+
This project is based heavily on work originally done by [igorw][4].
151+
Thanks Igor. :)
152+
153+
154+
[1]: https://github.com
155+
[2]: https://github.com/dflydev/git-subsplit
156+
[3]: http://getcomposer.org
157+
[4]: https://igor.io

bin/subsplit-worker.php

+98
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
<?php
2+
3+
require __DIR__.'/../vendor/autoload.php';
4+
5+
$configFilename = file_exists(__DIR__.'/../config.json')
6+
? __DIR__.'/../config.json'
7+
: __DIR__.'/../config.json.dist';
8+
9+
$config = json_decode(file_get_contents($configFilename), true);
10+
11+
$start = time();
12+
13+
$redis = new Predis\Client(array('read_write_timeout' => 0,));
14+
while ($body = $redis->brpoplpush('dflydev-git-subsplit:incoming', 'dflydev-git-subsplit:processing', 0)) {
15+
$data = json_decode($body, true);
16+
$name = null;
17+
$project = null;
18+
19+
$data['dflydev_git_subsplit'] = array(
20+
'processed_at' => time(),
21+
);
22+
23+
foreach ($config['projects'] as $testName => $testProject) {
24+
if ($testProject['url'] === $data['repository']['url']) {
25+
$name = $testName;
26+
$project = $testProject;
27+
break;
28+
}
29+
}
30+
31+
if (null === $name) {
32+
print(sprintf('Skipping request for URL %s (not configured)', $data['repository']['url'])."\n");
33+
34+
$redis->lrem('dflydev-git-subsplit:processing', 1, $body);
35+
$redis->lpush('dflydev-git-subspilt:failures', json_encode($data));
36+
continue;
37+
}
38+
39+
$data['dflydev_git_subsplit']['name'] = $name;
40+
$data['dflydev_git_subsplit']['project'] = $project;
41+
42+
$ref = $data['ref'];
43+
44+
$publishCommand = array(
45+
'git subsplit publish',
46+
escapeshellarg(implode(' ', $project['splits'])),
47+
);
48+
49+
if (preg_match('/refs\/tags\/(.+)$/', $ref, $matches)) {
50+
$publishCommand[] = escapeshellarg('--rebuild-tags');
51+
$publishCommand[] = escapeshellarg('--no-heads');
52+
$publishCommand[] = escapeshellarg(sprintf('--tags=%s', $matches[1]));
53+
} elseif (preg_match('/refs\/heads\/(.+)$/', $ref, $matches)) {
54+
$publishCommand[] = escapeshellarg('--no-tags');
55+
$publishCommand[] = escapeshellarg(sprintf('--heads=%s', $matches[1]));
56+
} else {
57+
print sprintf('Skipping request for URL %s (unexpected reference detected: %s)', $data['repository']['url'], $ref)."\n";
58+
59+
$redis->lrem('dflydev-git-subsplit:processing', 1, $body);
60+
$redis->lpush('dflydev-git-subspilt:failures', json_encode($data));
61+
continue;
62+
}
63+
64+
$repositoryUrl = isset($project['repository-url'])
65+
? $project['repository-url']
66+
: $project['url'];
67+
68+
print sprintf('Processing subsplit for %s (%s)', $name, $ref)."\n";
69+
70+
$projectWorkingDirectory = $config['working-directory'].'/'.$name;
71+
if (!file_exists($projectWorkingDirectory)) {
72+
print sprintf('Creating working directory for project %s (%s)', $name, $projectWorkingDirectory)."\n";
73+
mkdir($projectWorkingDirectory, 0750, true);
74+
}
75+
76+
$command = implode(' && ', array(
77+
sprintf('cd %s', $projectWorkingDirectory),
78+
sprintf('( git subsplit init %s || true )', $repositoryUrl),
79+
'git subsplit update',
80+
implode(' ', $publishCommand)
81+
));
82+
83+
passthru($command, $exitCode);
84+
85+
if (0 !== $exitCode) {
86+
print sprintf('Command %s had a problem, exit code %s', $command, $exitCode)."\n";
87+
88+
$redis->lrem('dflydev-git-subsplit:processing', 1, $body);
89+
$redis->lpush('dflydev-git-subspilt:failures', json_encode($data));
90+
continue;
91+
}
92+
93+
$redis->lrem('dflydev-git-subsplit:processing', 1, $body);
94+
$redis->rpush('dflydev-git-subsplit:processed', json_encode($data));
95+
}
96+
97+
$seconds = time() - $start;
98+
throw new \RuntimeException(sprintf('Something strange happened after %s seconds', $seconds));

composer.json

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
{
2+
"name": "dflydev/git-subsplit-github-webhook",
3+
"description": "GitHub WebHook for Git subsplits managed by dflydev-git-subsplit",
4+
"keywords": ["github", "webhook", "subsplit"],
5+
"license": "MIT",
6+
"authors": [
7+
{
8+
"name": "Dragonfly Development Inc.",
9+
"email": "[email protected]",
10+
"homepage": "http://dflydev.com"
11+
},
12+
{
13+
"name": "Beau Simensen",
14+
"email": "[email protected]",
15+
"homepage": "http://beausimensen.com"
16+
}
17+
],
18+
"require": {
19+
"php": ">=5.3.3",
20+
"predis/predis": "0.8.*"
21+
},
22+
"extra": {
23+
"branch-alias": {
24+
"dev-master": "1.0-dev"
25+
}
26+
}
27+
}

composer.lock

+61
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

config.json.dist

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
{
2+
"working-directory": "/tmp/dflydev-git-subsplit-github-webhook-working",
3+
"projects": {
4+
"sculpin": {
5+
"url": "https://github.com/sculpin/sculpin",
6+
"splits": [
7+
"src/Sculpin/Core:[email protected]:sculpin/core.git"
8+
]
9+
},
10+
"react": {
11+
"url": "https://github.com/reactphp/react",
12+
"splits": [
13+
"src/React/EventLoop:[email protected]:reactphp/event-loop.git",
14+
"src/React/Stream:[email protected]:reactphp/stream.git",
15+
"src/React/Cache:[email protected]:reactphp/cache.git",
16+
"src/React/Socket:[email protected]:reactphp/socket.git",
17+
"src/React/Http:[email protected]:reactphp/http.git",
18+
"src/React/HttpClient:[email protected]:reactphp/http-client.git",
19+
"src/React/Dns:[email protected]:reactphp/dns.git"
20+
]
21+
}
22+
}
23+
}

web/index.html

Whitespace-only changes.

0 commit comments

Comments
 (0)