Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge commit 'b13ec1ce8c8571943659d933d8cf081f8dee9058' as 'applicati…
…ons/githook'
- Loading branch information
Showing
4 changed files
with
200 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
*.lua |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
The MIT License (MIT) | ||
|
||
Copyright (c) 2016 Paul Liverman III | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
of this software and associated documentation files (the "Software"), to deal | ||
in the Software without restriction, including without limitation the rights | ||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
copies of the Software, and to permit persons to whom the Software is | ||
furnished to do so, subject to the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be included in all | ||
copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
SOFTWARE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
## Installation | ||
|
||
(Note: I'm going to rewrite this to explain how to use with locator, a simple | ||
server locator I designed for use with Lapis and these sub-applications.) | ||
|
||
Dependencies: | ||
|
||
- Lapis (duh) | ||
- MoonScript | ||
- OpenResty user needs a bash shell (ch -s /bin/bash user) | ||
|
||
From the shell: | ||
|
||
```bash | ||
git subtree add --prefix githook https://github.com/lazuscripts/githook.git master --squash | ||
``` | ||
|
||
(`--prefix` specifies where it will be saved.) | ||
|
||
Alternately, you can add it as a remote for easier maintenance: | ||
|
||
```bash | ||
git remote add -f githook https://github.com/lazuscripts/githook.git | ||
git subtree add --prefix githook githook master --squash | ||
``` | ||
|
||
From your main application class: `@include "githook.githook"` (or wherever you put it) | ||
|
||
### Updating | ||
|
||
From the shell: | ||
|
||
```bash | ||
git subtree pull --prefix githook https://github.com/lazuscripts/githook.git master --squash | ||
``` | ||
|
||
Or, if it is set up as remote: | ||
|
||
```bash | ||
git subtree pull --prefix githook githook master --squash | ||
``` | ||
|
||
## Config | ||
|
||
All configuration is optional. Without configuration, will attempt to update any | ||
time it is visited. | ||
|
||
- `githook_branch "branch"` which branch you want updating (as string) | ||
(to prevent updates triggering when pushing unrelated branches) | ||
- `githook_secret "secret"` the secret string used on GitHub | ||
|
||
Will attempt to checkout, pull, update submodules if needed, compile all code, | ||
then run migrations, and finally update the running server without interruption. | ||
|
||
Returns a log along with exit codes on success or failure. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
lapis = require "lapis" | ||
config = require("lapis.config").get! | ||
|
||
import respond_to, json_params from require "lapis.application" | ||
import hmac_sha1 from require "lapis.util.encoding" | ||
import insert from table | ||
|
||
const_compare = (string1, string2) -> | ||
local fail, dummy | ||
|
||
for i = 1, 100 | ||
if string1\sub(i,i) ~= string2\sub(i,i) | ||
fail = true | ||
else | ||
dummy = true -- attempting to make execution time equal | ||
|
||
return not fail | ||
|
||
hex_dump = (str) -> | ||
len = string.len str | ||
hex = "" | ||
|
||
for i = 1, len | ||
hex ..= string.format( "%02x", string.byte( str, i ) ) | ||
|
||
return hex | ||
|
||
execute = (cmd, capture_exit_code=true) -> | ||
local handle | ||
if capture_exit_code | ||
handle = io.popen "#{cmd}\necho $?" | ||
else | ||
handle = io.popen cmd | ||
result = handle\read "*a" | ||
handle\close! | ||
return result | ||
|
||
run_update = (branch) -> | ||
log = {} | ||
insert log, execute "git checkout #{branch} 2> /dev/stdout" | ||
insert log, execute "git pull origin 2> /dev/stdout" | ||
insert log, execute "git submodule init 2> /dev/stdout" | ||
insert log, execute "git submodule update 2> /dev/stdout" | ||
-- captures its own exit code at the end | ||
insert log, execute "code=0\nfor file in $(find . -type f -name \"*.moon\"); do moonc \"$file\" 2> /dev/stdout\ntmp=$?\nif [ ! $tmp -eq 0 ]; then code=$tmp\nfi; done\necho $code", false | ||
insert log, execute "lapis migrate #{config._name} 2> /dev/stdout" | ||
insert log, execute "lapis build #{config._name} 2> /dev/stdout" | ||
|
||
exit_codes = {} | ||
failure = false | ||
full_log = "" | ||
for result in *log | ||
exit_start, exit_end = result\find "(%d*)[%c]$" | ||
exit_code = tonumber result\sub(exit_start, exit_end)\sub 1, -2 | ||
|
||
output = result\sub 1, exit_start - 1 | ||
full_log ..= output | ||
|
||
-- this sequence should not be needed, I am leaving it temporarily | ||
if exit_code == nil -- this happens for the moonc calls | ||
if output\find "Failed to parse" -- so we search for an error | ||
exit_code = 1 | ||
else | ||
exit_code = 0 -- and I don't think there are other types of errors... | ||
insert exit_codes, 9001 -- means a NIL exit code happened somehow | ||
|
||
failure = true if exit_code != 0 | ||
insert exit_codes, exit_code | ||
|
||
if failure | ||
return status: 500, json: { | ||
status: "failure" | ||
message: "a subprocess returned a non-zero exit code" | ||
log: full_log | ||
:exit_codes | ||
} | ||
else | ||
return status: 200, json: { | ||
status: "success" | ||
message: "server updated to latest version of '#{branch}'" | ||
log: full_log | ||
:exit_codes | ||
} | ||
|
||
ignored = (branch) -> | ||
return status: 200, json: { | ||
status: "success" | ||
message: "ignored push (looking for updates to '#{branch}')" | ||
} | ||
|
||
class extends lapis.Application | ||
[githook: "/githook"]: respond_to { | ||
GET: => | ||
return status: 405, "Method Not Allowed" | ||
|
||
POST: json_params => | ||
branch = config.githook_branch or "master" | ||
if config.githook_secret | ||
ngx.req.read_body! | ||
if body = ngx.req.get_body_data! | ||
authorized = const_compare "sha1=#{hex_dump hmac_sha1 config.githook_secret, body}", @req.headers["X-Hub-Signature"] | ||
unless authorized | ||
return status: 401, "Unauthorized" | ||
if @params.ref == "refs/heads/#{branch}" | ||
return run_update branch | ||
elseif @params.ref == nil | ||
return status: 400, json: { | ||
status: "invalid request" | ||
message: "'ref' not defined in request body" | ||
} | ||
else | ||
return ignored branch | ||
else | ||
return status: 400, json: { | ||
status: "invalid request" | ||
message: "no request body" | ||
} | ||
else | ||
if @params.ref == "refs/heads/#{branch}" | ||
return run_update branch | ||
else | ||
return ignored branch | ||
} |