grim/convey
Clone
Summary
Browse
Changes
Graph
Add a .reviewboardrc file
2022-03-26, Gary Kramlich
8fea0c778f8e
Add a .reviewboardrc file
// Convey
// Copyright 2016-2018 Gary Kramlich <grim@reaperworld.com>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
// Package stages contains the stages api.
package
runtime
import
(
"fmt"
"sync"
log
"github.com/sirupsen/logrus"
"keep.imfreedom.org/grim/convey/environment"
"keep.imfreedom.org/grim/convey/logging"
"keep.imfreedom.org/grim/convey/yaml"
)
const
(
RunAlways
=
"always"
RunOnFailure
=
"on-failure"
RunOnSuccess
=
"on-success"
)
// Stage is a representation of a stage.
type
Stage
struct
{
Name
string
`yaml:"name"`
Run
string
`yaml:"run"`
Environment
yaml
.
StringOrSlice
`yaml:"environment"`
Tasks
yaml
.
StringOrSlice
`yaml:"tasks"`
Enabled
bool
`yaml:"enabled"`
Concurrent
bool
`yaml:"concurrent"`
}
// UnmarshalYAML is a custom yaml unmarshaller for stages.
func
(
s
*
Stage
)
UnmarshalYAML
(
unmarshal
func
(
interface
{})
error
)
error
{
type
rawStage
Stage
raw
:=
rawStage
{
Enabled
:
true
}
if
err
:=
unmarshal
(
&
raw
);
err
!=
nil
{
return
err
}
*
s
=
Stage
(
raw
)
// validate the run attribute
switch
s
.
Run
{
case
RunOnSuccess
:
case
RunOnFailure
:
case
RunAlways
:
case
""
:
s
.
Run
=
RunOnSuccess
default
:
return
fmt
.
Errorf
(
"Invalid value '%s' for run attribute"
,
s
.
Run
)
}
return
nil
}
// Execute runs the stage.
func
(
s
*
Stage
)
Execute
(
path
string
,
logger
*
log
.
Entry
,
env
environment
.
Environment
,
rt
*
Runtime
)
error
{
stageEnv
:=
env
.
Copy
().
Merge
(
env
).
MergeSlice
(
s
.
Environment
)
if
s
.
Concurrent
&&
!
rt
.
ForceSequential
{
taskRes
:=
make
(
chan
error
)
stageRes
:=
make
(
chan
error
)
wg
:=
sync
.
WaitGroup
{}
// process all of the task results
go
func
(
taskRes
,
stageRes
chan
error
)
{
var
stageErr
error
for
err
:=
range
taskRes
{
if
err
!=
nil
&&
stageErr
==
nil
{
stageErr
=
err
}
}
stageRes
<-
stageErr
// now close the stageRes channel
close
(
stageRes
)
}(
taskRes
,
stageRes
)
// run all of the tasks in go routines
for
_
,
taskName
:=
range
s
.
Tasks
{
wg
.
Add
(
1
)
go
func
(
path
,
name
string
,
res
chan
error
)
{
defer
wg
.
Done
()
res
<-
s
.
runTask
(
path
,
name
,
stageEnv
,
rt
)
}(
path
,
taskName
,
taskRes
)
}
// block until the task wait group is done, then close the taskRes channel
wg
.
Wait
()
close
(
taskRes
)
// now return the result from the stageRes channel
return
<-
stageRes
}
// serial execution
for
_
,
taskName
:=
range
s
.
Tasks
{
err
:=
s
.
runTask
(
path
,
taskName
,
stageEnv
,
rt
)
if
err
!=
nil
{
return
err
}
}
return
nil
}
func
(
s
*
Stage
)
runTask
(
path
,
name
string
,
stageEnv
environment
.
Environment
,
rt
*
Runtime
)
error
{
absTaskName
:=
fmt
.
Sprintf
(
"%s/%s"
,
path
,
name
)
taskLogger
:=
logging
.
NewAdapter
(
fmt
.
Sprintf
(
"%s/%s"
,
path
,
name
))
taskLogger
.
Info
(
"starting"
)
task
,
found
:=
rt
.
Tasks
[
name
]
if
!
found
{
taskLogger
.
Error
(
"failed, task not found"
)
return
fmt
.
Errorf
(
"task %s not found"
,
absTaskName
)
}
err
:=
task
.
Execute
(
absTaskName
,
taskLogger
,
stageEnv
,
rt
)
if
err
!=
nil
{
taskLogger
.
Errorf
(
"failed, %s"
,
err
)
return
err
}
taskLogger
.
Info
(
"finished"
)
return
nil
}
// ShouldRun will return True if a stage should be run based on the passed in
// error (from the plan) and whether or not the stage is enabled.
func
(
s
*
Stage
)
ShouldRun
(
err
error
)
bool
{
if
!
s
.
Enabled
{
return
false
}
if
s
.
Run
==
RunAlways
{
return
true
}
if
err
!=
nil
{
return
s
.
Run
==
RunOnFailure
}
return
s
.
Run
==
RunOnSuccess
}