Skip to content

Commit

Permalink
Merge commit 'b13ec1ce8c8571943659d933d8cf081f8dee9058' as 'applicati…
Browse files Browse the repository at this point in the history
…ons/githook'
  • Loading branch information
TangentFoxy committed Feb 19, 2018
2 parents 1bca4b8 + b13ec1c commit fd6aa40
Show file tree
Hide file tree
Showing 4 changed files with 200 additions and 0 deletions.
1 change: 1 addition & 0 deletions applications/githook/.gitignore
@@ -0,0 +1 @@
*.lua
21 changes: 21 additions & 0 deletions applications/githook/LICENSE
@@ -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.
55 changes: 55 additions & 0 deletions applications/githook/ReadMe.md
@@ -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.
123 changes: 123 additions & 0 deletions applications/githook/githook.moon
@@ -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
}

0 comments on commit fd6aa40

Please sign in to comment.