Added error handling and logging
This commit is contained in:
parent
a5660ba38f
commit
6f53ea70c0
@ -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
|
||||||
|
@ -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)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
96
project.go
96
project.go
@ -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()
|
||||||
|
Loading…
Reference in New Issue
Block a user