Added error handling and logging

This commit is contained in:
Tim Shannon 2016-03-31 22:32:56 -05:00
parent a5660ba38f
commit 6f53ea70c0
3 changed files with 84 additions and 36 deletions

View File

@ -12,11 +12,8 @@ You'll setup a project which will need the following information:
* Choose between polling for changes, or triggered builds * Choose between polling for changes, or triggered builds
* Triggered builds will be triggered off of a web hook POST call * Triggered builds will be triggered off of a web hook POST call
2. Script to build the repository 2. Script to build the repository
* Can have multiple scripts run in sequence
3. Script to test the repository 3. Script to test the repository
* Can have multiple scripts run in sequence
4. Script to build the release file 4. Script to build the release file
* Should create one file
5. Path to the release file 5. Path to the release file
6. Script to set release name / version 6. Script to set release name / version
* If script doesn't return a unique name, ironsmith will append a timestamp * If script doesn't return a unique name, ironsmith will append a timestamp

View File

@ -4,7 +4,12 @@
package datastore package datastore
import "time" import (
"encoding/json"
"time"
"github.com/boltdb/bolt"
)
type release struct { type release struct {
When time.Time `json:"when"` When time.Time `json:"when"`
@ -28,15 +33,17 @@ func (ds *Store) AddRelease(version string, fileData []byte) error {
FileKey: fileKey, FileKey: fileKey,
} }
err := ds.put(bucketReleases, key, r) dsValue, err := json.Marshal(r)
if err != nil { if err != nil {
return err return err
} }
err = ds.put(bucketFiles, fileKey, fileData) return ds.bolt.Update(func(tx *bolt.Tx) error {
err = tx.Bucket([]byte(bucketReleases)).Put(key.Bytes(), dsValue)
if err != nil { if err != nil {
return err return err
} }
return nil return tx.Bucket([]byte(bucketFiles)).Put(fileKey.Bytes(), fileData)
})
} }

View File

@ -7,17 +7,28 @@ package main
import ( import (
"encoding/json" "encoding/json"
"errors" "errors"
"fmt"
"io/ioutil" "io/ioutil"
"log"
"os" "os"
"path/filepath" "path/filepath"
"strings" "strings"
"sync" "sync"
"time" "time"
"git.townsourced.com/ironsmith/datastore"
) )
const enabledProjectDir = "enabled" const enabledProjectDir = "enabled"
//stages
const (
stageLoad = "load"
stageFetch = "fetch"
stageBuild = "build"
stageTest = "test"
stageRelease = "release"
)
// Project is an ironsmith project that contains how to fetch, build, test, and release a project // Project is an ironsmith project that contains how to fetch, build, test, and release a project
/* /*
The project lifecycle goes like this, each step calling the next if successful The project lifecycle goes like this, each step calling the next if successful
@ -43,6 +54,9 @@ type Project struct {
filename string filename string
poll time.Duration poll time.Duration
ds *datastore.Store
stage string
version string
} }
const projectTemplateFilename = "template.project.json" const projectTemplateFilename = "template.project.json"
@ -91,36 +105,55 @@ func prepTemplateProject() error {
return nil return nil
} }
func (p *Project) load() error { func (p *Project) errHandled(err error) bool {
if err == nil {
return false
}
if p.ds == nil {
log.Printf("Error in project %s: %s", p.filename, err)
return true
}
p.ds.AddLog(p.version, p.stage, err.Error())
return true
}
func (p *Project) load() {
if p.filename == "" { if p.filename == "" {
return fmt.Errorf("Invalid project file name") p.errHandled(errors.New("Invalid project file name"))
return
} }
if !projects.exists(p.filename) { if !projects.exists(p.filename) {
// project has been deleted // project has been deleted
// don't continue polling // don't continue polling
// TODO: Clean up Project data folder? // TODO: Clean up Project data folder?
return nil return
} }
data, err := ioutil.ReadFile(filepath.Join(projectDir, enabledProjectDir, p.filename)) data, err := ioutil.ReadFile(filepath.Join(projectDir, enabledProjectDir, p.filename))
if err != nil { if p.errHandled(err) {
return err return
}
err = json.Unmarshal(data, p)
if err != nil {
return err
} }
err = p.prepData() if p.errHandled(json.Unmarshal(data, p)) {
if err != nil { return
return err
} }
p.stage = stageLoad
if p.errHandled(p.prepData()) {
return
}
//TODO: call fetch
if p.PollInterval != "" { if p.PollInterval != "" {
p.poll, err = time.ParseDuration(p.PollInterval) p.poll, err = time.ParseDuration(p.PollInterval)
if err != nil { if p.errHandled(err) {
//TODO: Log pollInterval parse failure in project store
p.poll = 0 p.poll = 0
} }
} }
@ -129,7 +162,6 @@ func (p *Project) load() error {
//start polling //start polling
} }
return nil
} }
// prepData makes sure the project's data folder and data store is created // prepData makes sure the project's data folder and data store is created
@ -139,15 +171,20 @@ func (p *Project) load() error {
*/ */
func (p *Project) prepData() error { func (p *Project) prepData() error {
var dirName = strings.TrimSuffix(p.filename, filepath.Ext(p.filename)) var name = strings.TrimSuffix(p.filename, filepath.Ext(p.filename))
err := os.MkdirAll(filepath.Join(dataDir, dirName), 0777) var dir = filepath.Join(dataDir, name)
err := os.MkdirAll(dir, 0777)
if err != nil { if err != nil {
return err return err
} }
//TODO: Create data store p.ds, err = datastore.Open(filepath.Join(dir, name+".ironsmith"))
return errors.New("TODO") if err != nil {
return err
}
return nil
} }
type projectList struct { type projectList struct {
@ -181,20 +218,27 @@ func (p *projectList) load() error {
for i := range files { for i := range files {
if !files[i].IsDir() && filepath.Ext(files[i].Name()) == ".json" { if !files[i].IsDir() && filepath.Ext(files[i].Name()) == ".json" {
prj := &Project{filename: files[i].Name()} prj := &Project{
filename: files[i].Name(),
Name: files[i].Name(),
version: "starting up",
stage: stageLoad,
}
p.data[files[i].Name()] = prj p.data[files[i].Name()] = prj
err = prj.load() prj.load()
if err != nil {
delete(p.data, files[i].Name())
return err
}
} }
} }
return nil return nil
} }
func (p *projectList) remove(name string) {
p.Lock()
delete(p.data, name)
p.Unlock()
}
func (p *projectList) exists(name string) bool { func (p *projectList) exists(name string) bool {
p.RLock() p.RLock()
defer p.RUnlock() defer p.RUnlock()