58 Commits
v1.1 ... master

Author SHA1 Message Date
eaf4d9c4f5 gobs webhook test 2016-07-05 12:19:56 -05:00
cb9cea887e Merge branch 'master' of git.townsourced.com:townsourced/ironsmith 2016-07-05 12:17:42 -05:00
74c85da725 Merge branch 'master' of https://git.townsourced.com/townsourced/ironsmith 2016-06-23 16:50:37 -05:00
29412a68ff Merge branch 'master' of https://git.townsourced.com/townsourced/ironsmith 2016-06-23 16:41:42 -05:00
2bc13eca6c Merge branch 'master' of https://git.townsourced.com/townsourced/ironsmith 2016-06-23 16:36:23 -05:00
f8d5ddb469 removed verbose from build script 2016-05-05 10:51:57 -05:00
3bbb8d7c20 removed verbose from build script 2016-05-05 10:51:57 -05:00
c7745beb28 removed verbose from build script 2016-05-05 10:51:57 -05:00
f4dea30265 Changed forced build to be only off of trigger
instead of anytime that it's not polled
2016-05-05 10:30:50 -05:00
479175baa0 Changed forced build to be only off of trigger
instead of anytime that it's not polled
2016-05-05 10:30:50 -05:00
dbf41e948b Changed forced build to be only off of trigger
instead of anytime that it's not polled
2016-05-05 10:30:50 -05:00
1e3eb54ea2 Added max version limit for projects 2016-05-04 15:39:56 -05:00
b1c259640e Added max version limit for projects 2016-05-04 15:39:56 -05:00
35ec632334 Added max version limit for projects 2016-05-04 15:39:56 -05:00
52750bad48 Changed behavior so triggered builds ignore version
Version checks are only done on polling projects.
2016-05-04 08:35:36 -05:00
f75d91d4c0 Changed behavior so triggered builds ignore version
Version checks are only done on polling projects.
2016-05-04 08:35:36 -05:00
22db2cfdad Changed behavior so triggered builds ignore version
Version checks are only done on polling projects.
2016-05-04 08:35:36 -05:00
85d8ad8221 Added max project size starting point 2016-05-03 21:04:06 -05:00
f0e7c794c6 Added max project size starting point 2016-05-03 21:04:06 -05:00
d0b745cc9f Added max project size starting point 2016-05-03 21:04:06 -05:00
6e3ddacbf4 Fixed small issue with logs in table formatting 2016-04-28 15:12:50 +00:00
0ab64982da Fixed small issue with logs in table formatting 2016-04-28 15:12:50 +00:00
a5e982f508 Fixed small issue with logs in table formatting 2016-04-28 15:12:50 +00:00
ddbcb8fc6e Fixed last release file issue
trimmed logs in tables some more
2016-04-25 21:39:11 +00:00
1a161d9554 Fixed last release file issue
trimmed logs in tables some more
2016-04-25 21:39:11 +00:00
a3a7c4f66b Fixed last release file issue
trimmed logs in tables some more
2016-04-25 21:39:11 +00:00
6bca816d11 Changed log view formatting in tables a bit 2016-04-25 21:09:16 +00:00
07d499456b Changed log view formatting in tables a bit 2016-04-25 21:09:16 +00:00
21ebb286a6 Changed log view formatting in tables a bit 2016-04-25 21:09:16 +00:00
a4be249b2c Added time took to release log statement
Changed release file name handling to only include the base of the file
path.
2016-04-25 21:02:01 +00:00
8d79ded661 Added time took to release log statement
Changed release file name handling to only include the base of the file
path.
2016-04-25 21:02:01 +00:00
24b541801a Added time took to release log statement
Changed release file name handling to only include the base of the file
path.
2016-04-25 21:02:01 +00:00
0f165681ac Added pre-version version
No fetch and load errors can be properly seen without having to run
ironsmith manually.
2016-04-25 19:41:03 +00:00
04060ee63d Added pre-version version
No fetch and load errors can be properly seen without having to run
ironsmith manually.
2016-04-25 19:41:03 +00:00
345062d93a Added pre-version version
No fetch and load errors can be properly seen without having to run
ironsmith manually.
2016-04-25 19:41:03 +00:00
219efef570 Another small change in the same code 2016-04-25 16:56:48 +00:00
7a0b821be4 Another small change in the same code 2016-04-25 16:56:48 +00:00
e586626a69 Another small change in the same code 2016-04-25 16:56:48 +00:00
92a8045e13 Fixed issue with new projects
If they haven't done a single poll the UI was filing to find a last
version.
2016-04-25 16:51:01 +00:00
2066c68257 Fixed issue with new projects
If they haven't done a single poll the UI was filing to find a last
version.
2016-04-25 16:51:01 +00:00
6afd073f57 Fixed issue with new projects
If they haven't done a single poll the UI was filing to find a last
version.
2016-04-25 16:51:01 +00:00
1368f8aa50 Testing git hooks with ironsmith 2016-04-25 15:44:04 +00:00
4785efdfc2 Testing git hooks with ironsmith 2016-04-25 15:44:04 +00:00
dd12b9dfbf Testing git hooks with ironsmith 2016-04-25 15:44:04 +00:00
78d160247d Added / stole some code to handle cmd execs better
It'll now use any custom environment path to lookup executables to run
as part of the project scripts
2016-04-22 21:25:33 +00:00
01f655a2a1 Added / stole some code to handle cmd execs better
It'll now use any custom environment path to lookup executables to run
as part of the project scripts
2016-04-22 21:25:33 +00:00
6ca5b8668a Added better error handling.
Moved main project list columns around
2016-04-22 20:39:06 +00:00
0cabc10fd7 Added better error handling.
Moved main project list columns around
2016-04-22 20:39:06 +00:00
358b2069d6 Build script change 2016-04-21 13:41:21 +00:00
9cb1f8c347 Build script change 2016-04-21 13:41:21 +00:00
066ae7aa32 Updated build script 2016-04-20 16:42:16 +00:00
0908c91a7d Updated build script 2016-04-20 16:42:16 +00:00
9632d7f2b6 Post trigger test 2016-04-20 16:22:42 +00:00
19d11b456b Post trigger test 2016-04-20 16:22:42 +00:00
f0735abb32 Fixed issue with environment not getting set in projects 2016-04-20 16:15:53 +00:00
b1ee0c640e Fixed issue with environment not getting set in projects 2016-04-20 16:15:53 +00:00
cf681a83f5 Updated build script, and addded environment option for projects 2016-04-20 18:38:53 +05:00
481c2574a6 Updated build script, and addded environment option for projects 2016-04-20 06:38:53 +05:00
11 changed files with 151 additions and 47 deletions

View File

@ -14,7 +14,7 @@ You'll setup a project which will need the following information:
2. Script to build the repository
3. Script to test the repository
4. Script to build the release file
5. Path to the release file
5. Path to the release file / can also be a script that returns a file name
6. Script to set release name / version
An optional set of environment strings can be set to define the environment in which the scripts run.

File diff suppressed because one or more lines are too long

View File

@ -1,3 +1,3 @@
#!/bin/bash
go-bindata web/... && go build -a -v -o ironsmith
go-bindata web/... && go build -a -o ironsmith

View File

@ -27,12 +27,13 @@ Project life cycle:
// load is the beginning of the cycle. Loads / reloads the project file to make sure that the scripts are up-to-date
// call's fetch and triggers the next poll if one exists
func (p *Project) load() {
func (p *Project) load(forceBuild bool) {
p.processing.Lock() // ensure only one cycle is running at a time per project
defer p.processing.Unlock()
p.setStage(stageLoad)
p.setVersion("")
p.setVersion("Version not yet set")
p.start = time.Time{}
if p.filename == "" {
p.errHandled(errors.New("Invalid project file name"))
@ -63,25 +64,27 @@ func (p *Project) load() {
p.setData(new)
p.fetch()
p.fetch(forceBuild)
p.setStage(stageWait)
//full cycle completed
p.errHandled(p.ds.TrimVersions(p.MaxVersions))
if p.poll > 0 {
//start polling
go func() {
time.AfterFunc(p.poll, p.load)
}()
time.AfterFunc(p.poll, func() {
p.load(false)
})
}
}
// fetch first runs the fetch script into a temporary directory
// then it runs the version script in the temp directory to see if there is a newer version of the
// fetched code, if there is then the temp dir is renamed to the version name
func (p *Project) fetch() {
func (p *Project) fetch(forceBuild bool) {
p.setStage(stageFetch)
p.start = time.Now()
if p.Fetch == "" {
return
@ -108,18 +111,20 @@ func (p *Project) fetch() {
p.setVersion(strings.TrimSpace(string(version)))
// check if this specific version has attempted a build yet
lVer, err := p.ds.LastVersion(stageBuild)
if err != datastore.ErrNotFound && p.errHandled(err) {
return
}
if !forceBuild {
// if not forced build, then check if this specific version has attempted a build yet
lVer, err := p.ds.LastVersion(stageBuild)
if err != datastore.ErrNotFound && p.errHandled(err) {
return
}
if p.version == "" || p.version == lVer.Version {
// no new build clean up temp dir
p.errHandled(os.RemoveAll(tempDir))
if p.version == "" || p.version == lVer.Version {
// no new build clean up temp dir
p.errHandled(os.RemoveAll(tempDir))
vlog("No new version found for Project: %s Version: %s.\n", p.id(), p.version)
return
vlog("No new version found for Project: %s Version: %s.\n", p.id(), p.version)
return
}
}
//remove any existing data that matches version hash
@ -216,14 +221,15 @@ func (p *Project) release() {
return
}
if p.errHandled(p.ds.AddRelease(p.version, p.ReleaseFile, buff)) {
if p.errHandled(p.ds.AddRelease(p.version, filepath.Base(p.ReleaseFile), buff)) {
return
}
p.setStage(stageReleased)
if p.errHandled(p.ds.AddLog(p.version, p.stage,
fmt.Sprintf("Project %s Version %s built, tested, and released successfully.\n", p.id(), p.version))) {
fmt.Sprintf("Project %s Version %s built, tested, and released successfully and took %s.\n", p.id(), p.version,
time.Now().Sub(p.start)))) {
return
}

View File

@ -67,6 +67,83 @@ func (ds *Store) Close() error {
return ds.bolt.Close()
}
// TrimVersions Removes versions from the datastore file until it reaches the maxVersions count
func (ds *Store) TrimVersions(maxVersions int) error {
if maxVersions <= 0 {
// no max set
return nil
}
versions, err := ds.Versions()
if err != nil {
return err
}
if len(versions) <= maxVersions {
return nil
}
remove := versions[maxVersions:]
for i := range remove {
err = ds.deleteVersion(remove[i].Version)
if err != nil {
return err
}
}
return nil
}
// removes the earliest instance of a specific version
func (ds *Store) deleteVersion(version string) error {
return ds.bolt.Update(func(tx *bolt.Tx) error {
// remove all logs for this version
c := tx.Bucket([]byte(bucketLog)).Cursor()
for k, v := c.First(); k != nil; k, v = c.Next() {
lg := &Log{}
err := json.Unmarshal(v, lg)
if err != nil {
return err
}
if lg.Version != version {
break
}
err = c.Delete()
if err != nil {
return err
}
}
// remove all releases for this version
release, err := ds.Release(version)
if err == ErrNotFound {
return nil
}
if err != nil {
return err
}
err = tx.Bucket([]byte(bucketReleases)).Delete(release.FileKey.Bytes())
if err != nil {
return err
}
// remove release file for this version
err = tx.Bucket([]byte(bucketFiles)).Delete(release.FileKey.Bytes())
if err != nil {
return err
}
return nil
})
}
func (ds *Store) get(bucket string, key []byte, result interface{}) error {
return ds.bolt.View(func(tx *bolt.Tx) error {
dsValue := tx.Bucket([]byte(bucket)).Get(key)
@ -93,9 +170,3 @@ func (ds *Store) put(bucket string, key []byte, value interface{}) error {
return tx.Bucket([]byte(bucket)).Put(key, dsValue)
})
}
func (ds *Store) delete(bucket string, key []byte) error {
return ds.bolt.Update(func(tx *bolt.Tx) error {
return tx.Bucket([]byte(bucket)).Delete(key)
})
}

View File

@ -28,13 +28,13 @@ const (
// AddRelease adds a new Release
func (ds *Store) AddRelease(version, fileName string, fileData []byte) error {
fileKey := NewTimeKey()
key := NewTimeKey()
r := &Release{
When: fileKey.Time(),
When: key.Time(),
Version: version,
FileName: fileName,
FileKey: fileKey,
FileKey: key,
}
dsValue, err := json.Marshal(r)
@ -43,12 +43,12 @@ func (ds *Store) AddRelease(version, fileName string, fileData []byte) error {
}
return ds.bolt.Update(func(tx *bolt.Tx) error {
err = tx.Bucket([]byte(bucketReleases)).Put([]byte(version), dsValue)
err = tx.Bucket([]byte(bucketReleases)).Put(key.Bytes(), dsValue)
if err != nil {
return err
}
return tx.Bucket([]byte(bucketFiles)).Put(fileKey.Bytes(), fileData)
return tx.Bucket([]byte(bucketFiles)).Put(key.Bytes(), fileData)
})
}
@ -80,10 +80,27 @@ func (ds *Store) ReleaseFile(fileKey TimeKey) ([]byte, error) {
// Release gets the release record for a specific version
func (ds *Store) Release(version string) (*Release, error) {
r := &Release{}
err := ds.get(bucketReleases, []byte(version), r)
err := ds.bolt.View(func(tx *bolt.Tx) error {
c := tx.Bucket([]byte(bucketReleases)).Cursor()
for k, v := c.Last(); k != nil; k, v = c.Prev() {
err := json.Unmarshal(v, r)
if err != nil {
return err
}
if r.Version == version {
return nil
}
}
return ErrNotFound
})
if err != nil {
return nil, err
}
return r, nil
}
@ -119,9 +136,8 @@ func (ds *Store) LastRelease() (*Release, error) {
r := &Release{}
err := ds.bolt.View(func(tx *bolt.Tx) error {
c := tx.Bucket([]byte(bucketReleases)).Cursor()
_, v := tx.Bucket([]byte(bucketReleases)).Cursor().Last()
_, v := c.Last()
if v == nil {
return ErrNotFound
}

View File

@ -59,14 +59,14 @@ func lookPath(file string, env []string) (string, error) {
if err == nil {
return file, nil
}
return "", &exec.Error{file, err}
return "", &exec.Error{Name: file, Err: err}
}
for i := range env {
if strings.HasPrefix(env[i], "PATH=") {
pathenv := env[i][5:]
if pathenv == "" {
return "", &exec.Error{file, exec.ErrNotFound}
return "", &exec.Error{Name: file, Err: exec.ErrNotFound}
}
for _, dir := range strings.Split(pathenv, ":") {
if dir == "" {
@ -78,7 +78,7 @@ func lookPath(file string, env []string) (string, error) {
return path, nil
}
}
return "", &exec.Error{file, exec.ErrNotFound}
return "", &exec.Error{Name: file, Err: exec.ErrNotFound}
}
}

View File

@ -60,6 +60,7 @@ type Project struct {
ReleaseFile string `json:"releaseFile"`
PollInterval string `json:"pollInterval,omitempty"` // if not poll interval is specified, this project is trigger only
TriggerSecret string `json:"triggerSecret,omitempty"` //secret to be included with a trigger call
MaxVersions int `json:"maxVersions,omitempty"` // Max number of versions to keep in the project datastore
filename string
poll time.Duration
@ -68,6 +69,7 @@ type Project struct {
status string
version string
hash string
start time.Time // the last start time of the latest cycle
sync.RWMutex
processing sync.Mutex
@ -286,6 +288,7 @@ func (p *Project) setData(new *Project) {
p.ReleaseFile = new.ReleaseFile
p.PollInterval = new.PollInterval
p.TriggerSecret = new.TriggerSecret
p.MaxVersions = new.MaxVersions
if p.PollInterval != "" {
var err error
@ -323,6 +326,8 @@ var projectTemplate = &Project{
ReleaseFile: "release.tar.gz",
PollInterval: "15m",
MaxVersions: 100,
}
func prepTemplateProject() error {
@ -422,7 +427,7 @@ func (p *projectList) add(name string) {
log.Printf("Error opening datastore for Project: %s Error: %s\n", prj.id(), err)
return
}
prj.load()
prj.load(false)
}()
}

View File

@ -177,7 +177,7 @@
<td>
<a href="/project/{{.id}}/{{.lastLog.version}}">{{.lastLog.version}}</a>
</td>
<td title="{{.lastLog.log}}">{{#if .lastLog.log}}{{.lastLog.log.substring(0,100)}}{{/if}}</td>
<td title="{{.lastLog.log}}">{{#if .lastLog.log && .lastLog.log.length > 150}}{{.lastLog.log.substring(0,150)}}...{{else}}{{.lastLog.log}}{{/if}}</td>
<td>
<a href="/project/{{.id}}/{{.releaseVersion}}">{{.releaseVersion}}</a>
</td>
@ -213,7 +213,7 @@
<a href="/project/{{project.id}}/{{.version}}">{{.version}}</a>
</td>
<td>{{.stage}}</td>
<td title="{{.log}}">{{#if .log}}{{.log.substring(0,100)}}{{/if}}</td>
<td title="{{.log}}">{{#if .log && .log.length > 150}}{{.log.substring(0,150)}}...{{else}}{{.log}}{{/if}}</td>
<td>
{{#if releases[project.id + .version]}}
<a href="/release/{{project.id}}/{{.version}}?file">{{releases[project.id + .version].fileName}}</a>

View File

@ -135,7 +135,11 @@ Ractive.DEBUG = false;
function getVersion(id, version) {
get("/log/" + id + "/" + version,
function(result) {
r.set("version", version);
if (!result.data || !result.data.length || !result.data[0].version) {
r.set("version", version);
} else {
r.set("version", result.data[0].version);
}
r.set("stages", result.data);
},
function(result) {
@ -171,6 +175,8 @@ Ractive.DEBUG = false;
//statuses
if (project.stage != "waiting") {
project.status = project.stage;
} else if (!project.lastLog || !project.lastLog.version) {
project.status = "waiting";
} else if (project.lastLog.version.trim() == project.releaseVersion.trim()) {
project.status = "Successfully Released";
} else {

View File

@ -259,6 +259,6 @@ func triggerPost(w http.ResponseWriter, r *http.Request) {
}
go func() {
project.load()
project.load(true)
}()
}