Cleanup a bunch of lint and fix the broken unit tests. Refs #158
--- a/environment/environment.go Sat Jan 13 00:31:17 2018 -0600
+++ b/environment/environment.go Sat Jan 13 02:35:08 2018 -0600
@@ -56,6 +56,9 @@
+// Initialize sets a bunch of environment variables and then returns the name +// of them in a string slice. It will also determine what version control, if +// any is in use, and set variables for it as well. func Initialize(wd string) ([]string, error) {
oldHome := os.Getenv("HOME")
os.Setenv("HOME", "/tmp")
--- a/environment/mapper.go Sat Jan 13 00:31:17 2018 -0600
+++ b/environment/mapper.go Sat Jan 13 02:35:08 2018 -0600
@@ -27,10 +27,11 @@
-func (e *envMapper) Map(name string) string {
+// mapVariable replaces instances of the given name. +func (e *envMapper) mapVariable(name string) string { // We might have something like $(pwd), in which case we don't want
// to wrap the name in `{}`, which would cause it to be ${}(pwd) and
// cannot be evaluated by a run task.
@@ -55,7 +56,7 @@
// Map will return the value matching a KEY=VAL pair in the given environment.
func Map(key string, env []string) string {
+ return mapper.mapVariable(key) // Mapper will replace ${TEMPLATE} patterns in the string with the KEY=VAL pairs
@@ -66,10 +67,10 @@
- next := os.Expand(last, mapper.Map)
+ next := os.Expand(last, mapper.mapVariable) prev := map[string]struct{}{}
- for i := 0; i < MaxExpandWidth; i++ {
+ for i := 0; i < maxExpandWidth; i++ { @@ -79,7 +80,7 @@
- next = os.Expand(last, mapper.Map)
+ next = os.Expand(last, mapper.mapVariable) --- a/environment/merge.go Sat Jan 13 00:31:17 2018 -0600
+++ b/environment/merge.go Sat Jan 13 02:35:08 2018 -0600
@@ -1,20 +1,19 @@
- * Copyright 2016-2017 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/>.
+// 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/>. @@ -30,6 +29,7 @@
return parts[0], parts[1]
+// Merge combines two environments and returns the result. func Merge(orig, update []string) []string {
env := map[string]string{}
--- a/images/workspace-tools/zglob.go Sat Jan 13 00:31:17 2018 -0600
+++ b/images/workspace-tools/zglob.go Sat Jan 13 02:35:08 2018 -0600
@@ -1,26 +1,25 @@
- * Copyright 2017 Yasuhiro Matsumoto
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
+// Copyright 2017 Yasuhiro Matsumoto +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. --- a/intrinsic/clean.go Sat Jan 13 00:31:17 2018 -0600
+++ b/intrinsic/clean.go Sat Jan 13 02:35:08 2018 -0600
@@ -31,6 +31,7 @@
"bitbucket.org/rw_grim/convey/yaml"
+// Clean represents a clean task. Files yaml.StringOrSlice `yaml:"files"`
@@ -67,6 +68,7 @@
+// Execute runs the clean task. func (c *Clean) Execute(name string, logger *gomol.LogAdapter, env []string, st *state.State) error {
fullEnv := environment.Merge(env, st.GetEnv())
@@ -104,10 +106,12 @@
+// New creates a new clean task. func (c *Clean) New() tasks.Task {
+// Valid validates the clean task. func (c *Clean) Valid() error {
return fmt.Errorf("No files specified")
--- a/intrinsic/extend.go Sat Jan 13 00:31:17 2018 -0600
+++ b/intrinsic/extend.go Sat Jan 13 02:35:08 2018 -0600
@@ -27,6 +27,7 @@
"bitbucket.org/rw_grim/convey/yaml"
+// Extend represents a task that extends another task. Task string `yaml:"task"`
Environment yaml.StringOrSlice `yaml:"environment"`
@@ -40,6 +41,7 @@
+// Execute runs an extended task. func (e *Extend) Execute(name string, logger *gomol.LogAdapter, env []string, st *state.State) error {
// While extending, certain environment variables can be expanded into
// lists. We store this meta information as a stack on the state, which
@@ -52,10 +54,12 @@
+// New creates a new extend task. func (e *Extend) New() tasks.Task {
+// Valid validates the task. func (e *Extend) Valid() error {
if e.ExpandDelimiter == "" {
@@ -64,10 +68,12 @@
+// Dependencies returns a list of tasks that this task depends on. func (e *Extend) Dependencies() []string {
+// Resolve returns the fully extended task. func (e *Extend) Resolve(taskMap map[string]tasks.Task) error {
task, ok := taskMap[e.Task]
--- a/intrinsic/intrinsic.go Sat Jan 13 00:31:17 2018 -0600
+++ b/intrinsic/intrinsic.go Sat Jan 13 02:35:08 2018 -0600
@@ -22,6 +22,7 @@
+ // Tasks is a map of intrinsic tasks. Tasks = map[string]tasks.Task{
--- a/loaders/bitbucket/loader.go Sat Jan 13 00:31:17 2018 -0600
+++ b/loaders/bitbucket/loader.go Sat Jan 13 02:35:08 2018 -0600
@@ -34,6 +34,7 @@
"github.com/go-yaml/yaml"
+// Loader is a loader.Loader that loads bitbucket-pipelines.yml files func addTask(name string, task tasks.Task, plan plans.Plan, cfg *config.Config) {
@@ -171,6 +172,7 @@
+// Load loads the given filename and returns a config.Config for it. func (l *Loader) Load(base, path string, data []byte, disableDeprecated bool) (*config.Config, error) {
var pipeline bitbucketPipelines
err := yaml.Unmarshal(data, &pipeline)
@@ -235,22 +237,28 @@
+// LoadOverride loads the given override file into the config. func (l *Loader) LoadOverride(base, path string, data []byte, cfg *config.Config, disableDeprecated bool) {
+// Filenames returns the list for filenames that this loader supports. func (l *Loader) Filenames() []string {
return []string{"bitbucket-pipelines.yml"}
+// OverrideSuffix returns the suffix for override files. func (l *Loader) OverrideSuffix() string {
+// DefaultPlan returns the default plan name. func (l *Loader) DefaultPlan() string {
+// ResolvePlanName resolves the plan name if the one in the config contains a func (l *Loader) ResolvePlanName(plan string, cfg *config.Config, st *state.State) string {
// try to shortcut if we can
@@ -285,7 +293,7 @@
matchMapper["bookmark"] = append(matchMapper["bookmark"], hgBookmark)
- for name, _ := range cfg.Plans {
+ for name := range cfg.Plans { for prefix, matchers := range matchMapper {
for _, matcher := range matchers {
calculatedName := fmt.Sprintf("%s-%s", prefix, matcher)
--- a/loaders/convey/convey.go Sat Jan 13 00:31:17 2018 -0600
+++ b/loaders/convey/convey.go Sat Jan 13 02:35:08 2018 -0600
@@ -55,6 +55,7 @@
Options options `yaml:"options"`
+// Loader is a loader.Loader for loading convey.yml files. @@ -62,9 +63,10 @@
fileLoader func(string, *Loader) (*cConfig.Config, error)
-func (c *Loader) Load(path, base string, data []byte, disableDeprecated bool) (*cConfig.Config, error) {
- c.logger = logging.NewAdapter("config loader")
+// Load loads the given filename and returns it as a config.Config. +func (l *Loader) Load(path, base string, data []byte, disableDeprecated bool) (*cConfig.Config, error) { + l.logger = logging.NewAdapter("config loader") @@ -81,15 +83,15 @@
var baseConfig *cConfig.Config
- if c.depth >= MaxExtendsDepth {
+ if l.depth >= MaxExtendsDepth { return nil, ErrMaxExtendsDepth
extendsAbsName := filepath.Join(path, cfg.Extends)
- baseConfig, err = c.loadFile(extendsAbsName, disableDeprecated)
+ baseConfig, err = l.loadFile(extendsAbsName, disableDeprecated) // We can safely ignore no plans and no tasks errors here
// as we're ensured to also get a valid base config back.
@@ -108,7 +110,7 @@
// turn the raw tasks into real tasks
- realTasks, err := loadTasks(path, cfg.Tasks, c.logger, disableDeprecated)
+ realTasks, err := loadTasks(path, cfg.Tasks, l.logger, disableDeprecated) @@ -124,7 +126,7 @@
// store the default plan in the loader
- c.defaultPlan = cfg.Options.DefaultPlan
+ l.defaultPlan = cfg.Options.DefaultPlan // tasks, plans, and metaplans are all name => * maps, and
// if we're extending something we want to inherit all of these
@@ -166,7 +168,7 @@
// Check if the default plan is being overridden
if cfg.Options.DefaultPlan != "" {
- c.defaultPlan = cfg.Options.DefaultPlan
+ l.defaultPlan = cfg.Options.DefaultPlan // don't clobber ssh-identities with an empty list
@@ -180,7 +182,7 @@
// in the correct order. This is a problem, for example, if the extend
// intrinsic clones a task that is not fully resolved.
- if err := c.resolve(baseConfig); err != nil {
+ if err := l.resolve(baseConfig); err != nil { @@ -202,7 +204,7 @@
-func (c *Loader) resolve(baseConfig *cConfig.Config) error {
+func (l *Loader) resolve(baseConfig *cConfig.Config) error { // Extract resolvable tasks from config tasks
resolvables := map[string]tasks.ResolvableTask{}
@@ -271,15 +273,17 @@
-func (c *Loader) loadFile(path string, disableDeprecated bool) (*cConfig.Config, error) {
- if c.fileLoader == nil {
- return cConfig.LoadFile(path, c, disableDeprecated)
+// Load loads the given filename and returns it as a config.Config. +func (l *Loader) loadFile(path string, disableDeprecated bool) (*cConfig.Config, error) { + if l.fileLoader == nil { + return cConfig.LoadFile(path, l, disableDeprecated) - return c.fileLoader(path, c)
+ return l.fileLoader(path, l) -func (c *Loader) LoadOverride(path, base string, data []byte, config *cConfig.Config, disableDeprecated bool) {
+// LoadOverride loads the given override file into the given config.Config. +func (l *Loader) LoadOverride(path, base string, data []byte, config *cConfig.Config, disableDeprecated bool) { var overrideData override
err := yaml.Unmarshal(data, &overrideData)
@@ -291,7 +295,7 @@
// Check if the default plan is being overridden
if overrideData.Options.DefaultPlan != "" {
- c.defaultPlan = overrideData.Options.DefaultPlan
+ l.defaultPlan = overrideData.Options.DefaultPlan // if there are ssh-identities in the override they need to replace the
@@ -301,14 +305,17 @@
+// Filenames returns a string slice of filenames that are valid for this loader. func (l *Loader) Filenames() []string {
return []string{"convey.yml", "convey.yaml"}
+// OverrideSuffix returns the suffix for override filenames. func (l *Loader) OverrideSuffix() string {
+// DefaultPlan returns the default plan name. func (l *Loader) DefaultPlan() string {
@@ -317,6 +324,7 @@
+// ResolvePlanName resolves a plan name if wildcards are supported. func (l *Loader) ResolvePlanName(plan string, cfg *cConfig.Config, st *state.State) string {
--- a/loaders/convey/convey_test.go Sat Jan 13 00:31:17 2018 -0600
+++ b/loaders/convey/convey_test.go Sat Jan 13 02:35:08 2018 -0600
@@ -83,6 +83,7 @@
func (s *conveySuite) TestPlansRequired(t sweet.T) {
--- a/loaders/convey/default_plan_test.go Sat Jan 13 00:31:17 2018 -0600
+++ b/loaders/convey/default_plan_test.go Sat Jan 13 02:35:08 2018 -0600
@@ -44,6 +44,7 @@
default-plan: overridden-plan
@@ -63,6 +64,7 @@
func (d *defaultPlanSuite) TestDefaultPlanFromOverride(t sweet.T) {
--- a/loaders/convey/environment_test.go Sat Jan 13 00:31:17 2018 -0600
+++ b/loaders/convey/environment_test.go Sat Jan 13 02:35:08 2018 -0600
@@ -25,6 +25,7 @@
--- a/loaders/convey/errors.go Sat Jan 13 00:31:17 2018 -0600
+++ b/loaders/convey/errors.go Sat Jan 13 02:35:08 2018 -0600
@@ -21,11 +21,20 @@
+ // MaxExtendsDepth is the maximum depth that configs can extend each other. - ErrNoTasks = errors.New("no tasks specified")
- ErrNoPlans = errors.New("no plans specified")
+ // ErrNoTasks is used to represent a config that doesn't have any tasks + ErrNoTasks = errors.New("no tasks specified") + // ErrNoPlans is used to represent a config that doesn't have any plans + ErrNoPlans = errors.New("no plans specified") + // ErrMaxExtendsDepth is returned when a cycle has been found in configs + // that extend each other. ErrMaxExtendsDepth = errors.New("exceeded allowed depth for extended configs")
--- a/loaders/convey/extend_test.go Sat Jan 13 00:31:17 2018 -0600
+++ b/loaders/convey/extend_test.go Sat Jan 13 02:35:08 2018 -0600
@@ -32,12 +32,13 @@
@@ -62,17 +63,18 @@
@@ -102,10 +104,10 @@
@@ -122,7 +124,7 @@
@@ -141,6 +143,7 @@
@@ -152,7 +155,7 @@
@@ -184,10 +187,13 @@
@@ -213,6 +219,7 @@
@@ -232,6 +239,7 @@
@@ -279,6 +287,7 @@
@@ -290,6 +299,7 @@
@@ -312,6 +322,7 @@
@@ -325,6 +336,7 @@
@@ -349,6 +361,7 @@
--- a/loaders/convey/extends_test.go Sat Jan 13 00:31:17 2018 -0600
+++ b/loaders/convey/extends_test.go Sat Jan 13 02:35:08 2018 -0600
@@ -38,10 +38,13 @@
@@ -55,6 +58,7 @@
@@ -90,10 +94,13 @@
@@ -107,6 +114,7 @@
@@ -141,6 +149,7 @@
@@ -154,6 +163,7 @@
@@ -178,6 +188,7 @@
@@ -223,6 +234,7 @@
--- a/logging/adapter.go Sat Jan 13 00:31:17 2018 -0600
+++ b/logging/adapter.go Sat Jan 13 02:35:08 2018 -0600
@@ -22,6 +22,8 @@
"bitbucket.org/rw_grim/convey/color"
+// NewAdapter creates a new gomol.LogAdapter with attributes for the identifier +// as well has a color for it. func NewAdapter(identifier string) *gomol.LogAdapter {
attrs := gomol.NewAttrsFromMap(map[string]interface{}{
--- a/logging/logging.go Sat Jan 13 00:31:17 2018 -0600
+++ b/logging/logging.go Sat Jan 13 02:35:08 2018 -0600
@@ -14,7 +14,7 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
-// Packaging logging contains helpers for logging.
+// Package logging contains helpers for logging. --- a/network/network.go Sat Jan 13 00:31:17 2018 -0600
+++ b/network/network.go Sat Jan 13 02:35:08 2018 -0600
@@ -17,6 +17,7 @@
// Package network provides the interface creating networks.
+// Network is an interface for representing an isolated network. --- a/normalize/normalize.go Sat Jan 13 00:31:17 2018 -0600
+++ b/normalize/normalize.go Sat Jan 13 02:35:08 2018 -0600
@@ -29,6 +29,7 @@
re = regexp.MustCompile("[^._A-Za-z0-9-]")
+// Normalize normalizes the given string to be a valid identifier. func Normalize(in string) string {
return re.ReplaceAllLiteralString(in, "_")
--- a/path/path.go Sat Jan 13 00:31:17 2018 -0600
+++ b/path/path.go Sat Jan 13 02:35:08 2018 -0600
@@ -47,6 +47,8 @@
+// TraversesNonExistent works like Traverses but will walk up the path until it +// finds a directory that does exist. func TraversesNonExistent(root, path string) (string, error) {
// attempt to do a normal traversal
realPath, err := Traverses(root, path)
--- a/plans/metaplans.go Sat Jan 13 00:31:17 2018 -0600
+++ b/plans/metaplans.go Sat Jan 13 02:35:08 2018 -0600
@@ -20,10 +20,12 @@
+// MetaPlan is a representation of a meta plan. Plans []string `yaml:"plans"`
+// UnmarshalYAML is a custom yaml unmarshaller for MetaPlan's. func (m *MetaPlan) UnmarshalYAML(unmarshal func(interface{}) error) error {
type rawMetaPlan MetaPlan
--- a/plans/plans.go Sat Jan 13 00:31:17 2018 -0600
+++ b/plans/plans.go Sat Jan 13 02:35:08 2018 -0600
@@ -34,9 +34,11 @@
+ // ErrNoStages is an error that can be returned from Plan.Valid. ErrNoStages = errors.New("no stages found")
+// Plan is the representation of a Plan. Environment yaml.StringOrSlice `yaml:"environment"`
Stages []stages.Stage `yaml:"stages"`
@@ -98,6 +100,7 @@
+// Execute runs the plan. func (p *Plan) Execute(path string, tasks map[string]tasks.Task, env []string, st *state.State) error {
logger := logging.NewAdapter(path)
planEnv := environment.Merge(env, p.Environment)
@@ -144,6 +147,7 @@
+// Valid validates the plan. func (p *Plan) Valid() error {
--- a/runners/default.go Sat Jan 13 00:31:17 2018 -0600
+++ b/runners/default.go Sat Jan 13 02:35:08 2018 -0600
@@ -22,8 +22,10 @@
"bitbucket.org/rw_grim/convey/state"
+// Default is the normal Convey Runner. +// Run runs the Convey Runner. func (d *Default) Run(cfg *config.Config, plans []string, env []string, st *state.State) int {
logger := logging.NewAdapter("convey-runner")
/* now look for the plan */
--- a/runners/graphviz.go Sat Jan 13 00:31:17 2018 -0600
+++ b/runners/graphviz.go Sat Jan 13 02:35:08 2018 -0600
@@ -78,35 +78,37 @@
var normalizeRegex *regexp.Regexp
+ // Graphviz is a Runner that will create a graphviz output for the config + // that has been loaded.
- FallThroughs []GraphvizStage
+ FallThroughs []graphvizStage
- GraphvizMetaPlan struct {
+ graphvizMetaPlan struct {
@@ -118,11 +120,11 @@
return prefix + "_" + normalizeRegex.ReplaceAllString(str, "_")
-func (g *Graphviz) getTasks(cfg *config.Config) []GraphvizTask {
- tasks := []GraphvizTask{}
+func (g *Graphviz) getTasks(cfg *config.Config) []graphvizTask { + tasks := []graphvizTask{} - for name, _ := range cfg.Tasks {
+ for name := range cfg.Tasks { Normalized: normalize("task", name),
@@ -132,11 +134,11 @@
-func (g *Graphviz) getMetaPlans(cfg *config.Config) []GraphvizMetaPlan {
- metaPlans := []GraphvizMetaPlan{}
+func (g *Graphviz) getMetaPlans(cfg *config.Config) []graphvizMetaPlan { + metaPlans := []graphvizMetaPlan{} for name, cMetaPlan := range cfg.MetaPlans {
- metaPlan := GraphvizMetaPlan{
+ metaPlan := graphvizMetaPlan{ Normalized: normalize("metaplan", name),
@@ -154,16 +156,16 @@
-func (g Graphviz) plan(name string, plan plans.Plan) GraphvizPlan {
- graphvizPlan := GraphvizPlan{
+func (g Graphviz) plan(name string, plan plans.Plan) graphvizPlan { + graphvizPlan := graphvizPlan{ Normalized: normalize("plan", name),
- Stages: []GraphvizStage{},
+ Stages: []graphvizStage{}, for idx, stage := range plan.Stages {
- graphvizStage := GraphvizStage{
+ graphvizStage := graphvizStage{ Normalized: normalize("stage", stage.Name),
@@ -189,8 +191,8 @@
-func (g *Graphviz) getPlans(cfg *config.Config) []GraphvizPlan {
- plans := []GraphvizPlan{}
+func (g *Graphviz) getPlans(cfg *config.Config) []graphvizPlan { + plans := []graphvizPlan{} for name, plan := range cfg.Plans {
plans = append(plans, g.plan(name, plan))
@@ -199,6 +201,7 @@
+// Run runs the graphviz runner. func (g *Graphviz) Run(cfg *config.Config, plans []string, env []string, st *state.State) int {
logger := logging.NewAdapter("graphviz")
--- a/runners/listenvironment.go Sat Jan 13 00:31:17 2018 -0600
+++ b/runners/listenvironment.go Sat Jan 13 02:35:08 2018 -0600
@@ -26,8 +26,10 @@
"bitbucket.org/rw_grim/convey/state"
+// ListEnvironment is a runner that will output the environment. type ListEnvironment struct{}
+// Run runs the ListEnvironment runner. func (l *ListEnvironment) Run(cfg *config.Config, plans []string, env []string, st *state.State) int {
fmt.Printf("Builtins:\n")
--- a/runners/listmetaplans.go Sat Jan 13 00:31:17 2018 -0600
+++ b/runners/listmetaplans.go Sat Jan 13 02:35:08 2018 -0600
@@ -23,8 +23,10 @@
"bitbucket.org/rw_grim/convey/state"
+// ListMetaPlans is a Runner that outputs the metaplans for the loaded config. type ListMetaPlans struct{}
+// Run runs the ListMetaPlans runner. func (l *ListMetaPlans) Run(cfg *config.Config, plans []string, env []string, st *state.State) int {
for metaPlanName, metaPlan := range cfg.MetaPlans {
fmt.Printf("%s\n", metaPlanName)
--- a/runners/listplans.go Sat Jan 13 00:31:17 2018 -0600
+++ b/runners/listplans.go Sat Jan 13 02:35:08 2018 -0600
@@ -23,8 +23,10 @@
"bitbucket.org/rw_grim/convey/state"
+// ListPlans is a Runner that outputs the plans in the loaded config. +// Run runs the ListPlans Runner. func (l *ListPlans) Run(cfg *config.Config, plans []string, env []string, st *state.State) int {
for planName, plan := range cfg.Plans {
fmt.Printf("%s\n", planName)
--- a/runners/listtasks.go Sat Jan 13 00:31:17 2018 -0600
+++ b/runners/listtasks.go Sat Jan 13 02:35:08 2018 -0600
@@ -24,11 +24,13 @@
"bitbucket.org/rw_grim/convey/state"
+// ListTasks is a Runner that will output the tasks defined in a config. +// Run runs the ListTasks runner. func (l *ListTasks) Run(cfg *config.Config, plans []string, env []string, st *state.State) int {
- for taskName, _ := range config.TasksMap {
+ for taskName := range config.TasksMap { tasks = append(tasks, taskName)
--- a/runners/runners.go Sat Jan 13 00:31:17 2018 -0600
+++ b/runners/runners.go Sat Jan 13 02:35:08 2018 -0600
@@ -22,6 +22,7 @@
"bitbucket.org/rw_grim/convey/state"
+// Runner is an interface for defining something that convey can run. Run(cfg *config.Config, plan []string, env []string, st *state.State) int
--- a/runners/showconfig.go Sat Jan 13 00:31:17 2018 -0600
+++ b/runners/showconfig.go Sat Jan 13 02:35:08 2018 -0600
@@ -23,8 +23,10 @@
"bitbucket.org/rw_grim/convey/state"
+// ShowConfig is a Runner that will dump the config to stdout. +// Run runs the ShowConfig runner. func (sc *ShowConfig) Run(cfg *config.Config, plans []string, env []string, st *state.State) int {
--- a/ssh/agent.go Sat Jan 13 00:31:17 2018 -0600
+++ b/ssh/agent.go Sat Jan 13 02:35:08 2018 -0600
@@ -86,6 +86,7 @@
+// ShouldEnable returns true if the ssh agent should be enabled. func ShouldEnable(identities []string) (bool, error) {
if len(identities) <= 0 {
--- a/stages/stages.go Sat Jan 13 00:31:17 2018 -0600
+++ b/stages/stages.go Sat Jan 13 02:35:08 2018 -0600
@@ -31,6 +31,7 @@
"bitbucket.org/rw_grim/convey/yaml"
+// Stage is a representation of a stage. Name string `yaml:"name"`
Enabled bool `yaml:"enabled"`
@@ -41,6 +42,7 @@
Tasks yaml.StringOrSlice `yaml:"tasks"`
+// UnmarshalYAML is a custom yaml unmarshaller for stages. func (s *Stage) UnmarshalYAML(unmarshal func(interface{}) error) error {
raw := rawStage{Enabled: true}
@@ -77,6 +79,7 @@
+// Execute runs the stage. func (s *Stage) Execute(path string, logger *gomol.LogAdapter, taskMap map[string]tasks.Task, env []string, st *state.State) error {
stageEnv := environment.Merge(env, s.Environment)
--- a/state/state.go Sat Jan 13 00:31:17 2018 -0600
+++ b/state/state.go Sat Jan 13 02:35:08 2018 -0600
@@ -30,8 +30,9 @@
"bitbucket.org/rw_grim/convey/workspace"
-const ExpansionLimit = 100
+const expansionLimit = 100 +// State holds all of the runtime data during a run. CleanupList *cleanup.List
@@ -79,6 +80,7 @@
+// New creates a new state. runningContainers: map[string]struct{}{},
@@ -147,7 +149,7 @@
// never a useful case - a high expansion limit should catch this
// without ever hitting a practical edge.
- for i := 0; i < ExpansionLimit; i++ {
+ for i := 0; i < expansionLimit; i++ { next, err := st.expandSlice(prev, fullEnv)
--- a/state/state_test.go Sat Jan 13 00:31:17 2018 -0600
+++ b/state/state_test.go Sat Jan 13 02:35:08 2018 -0600
@@ -116,13 +116,13 @@
Expect(err.Error()).To(ContainSubstring("hit limit"))
-func (e *stateSuite) TestGetNames(t sweet.T) {
+func (s *stateSuite) TestGetNames(t sweet.T) { names := getNames("foo $bar ${baz} ${bar} $bonk_quux honk")
Expect(names).To(HaveLen(4))
Expect(names).To(ConsistOf([]string{"bar", "baz", "bar", "bonk_quux"}))
-func (e *stateSuite) TestProduct(t sweet.T) {
+func (s *stateSuite) TestProduct(t sweet.T) { p := product(map[string][]string{
"a": []string{"1", "2", "3"},
--- a/tasks/tasks.go Sat Jan 13 00:31:17 2018 -0600
+++ b/tasks/tasks.go Sat Jan 13 02:35:08 2018 -0600
@@ -23,12 +23,15 @@
"bitbucket.org/rw_grim/convey/state"
+// Task is an interface for defining a task that can be run. Execute(name string, logger *gomol.LogAdapter, env []string, st *state.State) error
+// ResolvableTask is used for extend tasks to make sure they're resolved in type ResolvableTask interface {
// Resolve is called by the loader once the current set of tasks
// by name have been loaded from the config file.