added notes.txt on the architecture, and a sample worker_config

pull/1/head
KatolaZ 8 years ago
parent 3b752dc02e
commit 32b0925615
  1. 101
      commits.go
  2. 2
      config.go
  3. 54
      notes.txt
  4. 11
      scorsh.go
  5. 37
      worker_config.cfg

@ -0,0 +1,101 @@
package main
import (
"fmt"
"github.com/KatolaZ/git2go"
"golang.org/x/crypto/openpgp"
"os"
"strings"
"log"
)
func CommitToString(commit *git.Commit) string {
var ret string
ret += fmt.Sprintf("type: %s\n", commit.Type())
ret += fmt.Sprintf("Id: %s\n", commit.Id())
ret += fmt.Sprintf("Author: %s\n", commit.Author())
ret += fmt.Sprintf("Message: %s\n", commit.Message())
ret += fmt.Sprintf("Parent-count: %d\n", commit.ParentCount())
return ret
}
// FIXME: RETURN THE ENTITY PROVIDED BY THE CHECK, OR nil
func check_signature(commit *git.Commit, keyring *openpgp.KeyRing) (signature, signed string, err error) {
signature, signed, err = commit.ExtractSignature()
if err == nil {
_, err_sig :=
openpgp.CheckArmoredDetachedSignature(*keyring, strings.NewReader(signed),
strings.NewReader(signature))
if err_sig == nil {
fmt.Printf("Good signature \n")
return signature, signed, nil
}
err = err_sig
}
return "", "", err
}
// traverse all the commits between two references, looking for scorsh
// commands
// fixme: we don't have just one keyring here....
func walk_commits(msg SCORSHmsg, keyring openpgp.KeyRing) int {
fmt.Printf("Inside parse_commits\n")
reponame := msg.repo
old_rev := msg.old_rev
new_rev := msg.new_rev
repo, err := git.OpenRepository(reponame)
if err != nil {
fmt.Fprintf(os.Stderr, "Error while opening repository %s (%s)\n",
reponame, err)
return SCORSH_ERR_NO_REPO
}
old_rev_oid, err := git.NewOid(old_rev)
oldrev_commit, err := repo.LookupCommit(old_rev_oid)
if err != nil {
fmt.Fprintf(os.Stderr, "Commit: %s does not exist\n", old_rev)
return SCORSH_ERR_NO_COMMIT
}
new_rev_oid, err := git.NewOid(new_rev)
newrev_commit, err := repo.LookupCommit(new_rev_oid)
if err != nil {
fmt.Fprintf(os.Stderr, "Commit: %s does not exist\n", new_rev)
return SCORSH_ERR_NO_COMMIT
}
cur_commit := newrev_commit
for cur_commit.Id().String() != oldrev_commit.Id().String() {
commit, err := repo.LookupCommit(cur_commit.Id())
if err == nil {
fmt.Printf("%s", CommitToString(commit))
//signature, signed, err := check_signature(commit, &keyring)
_, _, err := check_signature(commit, &keyring)
if err != nil {
log.Printf("%s\n", SCORSHErr(SCORSH_ERR_SIGNATURE))
}
cur_commit = commit.Parent(0)
} else {
fmt.Printf("Commit %x not found!\n", cur_commit.Id())
return SCORSH_ERR_NO_COMMIT
}
}
return 0
}

@ -28,7 +28,7 @@ type SCORSHcfg struct {
// Read a configuration from fname or die
func ReadConfig(fname string) *SCORSHcfg {
func ReadGlobalConfig(fname string) *SCORSHcfg {
data, err := ioutil.ReadFile(fname)
if err != nil {

@ -0,0 +1,54 @@
## structure
- we read the list of workers from the config file. Each worker
record consists of
- a list of repos/branches
- a folder where the configs and logs are kept
- a logfile
- a tagfile with the definition of tags
- a list of keyring files
## master logic
- in main() (master) we create a worker for each worker record,
maintaining a map of which worker can process commands for which
repo/branch
- The spooler receives and processes CREATE events from the spool. It
parses each message and forwards it to the corresponding worker(s).
- When the worker is done, it notifies the master, which will delete
the corresponding file from the spool.
## worker logic
- Each worker reads a configuration file containing the definition of
the tags it can manage.
- Each tag is associated to a set of commands (URLs) and to a set of
keyrings.
- A worker maintains a list of accepted scorsh tags, a map of
keyrings[tags], and a map of commands[tags].
When a new scorsh message is received by a worker, it looks through
the commit history for commits containing schorsh-tags. For each
scorsh-tag found, the worker looks if the tag is among the supported
ones, then checks if the commit can be verified by one of the keyrings
associated to the tag. If the set of keyrings for that tag is empty,
the tag is not allowed to run (this is a quick way to disable tags).
(we might want to add an option to the definition of a scorsh-tag,
which allows to run the commands from unsigned and/or unverified
commits. This would be very dangerous though.)
Then, if the tag is allowed to run, the worker executes each of the
commands in the tag definition, replacing arguments as needed. If a
command is a script (file://...), then it must also correspon to the
hash specified in the config, otherwise it will not be executed.
When the worker is finished with all the commands for all the commits,
it will notify the master.

@ -14,11 +14,6 @@ const (
SCORSH_ERR_SIGNATURE
)
type SCORSHconf struct {
spool string
}
type SCORSHmsg struct {
repo string
@ -60,8 +55,12 @@ func main() {
flag.Parse()
cfg := ReadConfig(*conf_file)
cfg := ReadGlobalConfig(*conf_file)
msg, status := StartWorkers(cfg)
log.Printf("%s\n", cfg)
}

@ -0,0 +1,37 @@
#
# This is the typical worker configuration file. The file should be
# called "worker_config.cfg", and will be placed inside the worker
# directory. It defines the tags understood by the worker, with the
# corresponding list of commands
#
#
---
w_tags:
[
{
t_name: "BUILD",
t_keyrings: ["build_keyring.asc", "general_keyring.asc"],
t_commands: [
{
c_url: "file:///home/user/bin/script.sh $1 $2",
c_hash: "12da324fb76s924acbce"
},
{
c_url: "http://my.server.net/call.pl?branch=$1"
}
]
},
{
t_name: "PUBLISH",
t_keyrings: ["web_developers.asc"],
t_commands: [
{
c_url: "file:///usr/local/bin/publish.py $repo $branch",
c_hash: "3234567898765432345678"
}
]
}
]
...
Loading…
Cancel
Save