func (r *Runner) Run() error {
	log.Printf("[DEBUG] (runner) initiating run")

	var newRenderEvent, wouldRenderAny, renderedAny bool
	runCtx := &templateRunCtx{
		depsMap: make(map[string]dep.Dependency),
	}

	for _, tmpl := range r.templates {
		event, err := r.runTemplate(tmpl, runCtx)
		if err != nil {
			return err
		}

		// If there was a render event store it
		if event != nil {
			r.renderEventsLock.Lock()
			r.renderEvents[tmpl.ID()] = event
			r.renderEventsLock.Unlock()

			// Record that there is at least one new render event
			newRenderEvent = true

			// Record that at least one template would have been rendered.
			if event.WouldRender {
				wouldRenderAny = true
			}

			// Record that at least one template was rendered.
			if event.DidRender {
				renderedAny = true
			}
		}
	}

	// Check if we need to deliver any rendered signals
	if wouldRenderAny || renderedAny {
		// Send the signal that a template got rendered
		select {
		case r.renderedCh <- struct{}{}:
		default:
		}
	}

	// Check if we need to deliver any event signals
	if newRenderEvent {
		select {
		case r.renderEventCh <- struct{}{}:
		default:
		}
	}

	// Perform the diff and update the known dependencies.
	r.diffAndUpdateDeps(runCtx.depsMap)

	// Execute each command in sequence, collecting any errors that occur - this
	// ensures all commands execute at least once.
	var errs []error
	for _, t := range runCtx.commands {
		command := config.StringVal(t.Exec.Command)
		log.Printf("[INFO] (runner) executing command %q from %s", command, t.Display())
		env := t.Exec.Env.Copy()
		env.Custom = append(r.childEnv(), env.Custom...)
		if _, err := spawnChild(&spawnChildInput{
			Stdin:        r.inStream,
			Stdout:       r.outStream,
			Stderr:       r.errStream,
			Command:      command,
			Env:          env.Env(),
			Timeout:      config.TimeDurationVal(t.Exec.Timeout),
			ReloadSignal: config.SignalVal(t.Exec.ReloadSignal),
			KillSignal:   config.SignalVal(t.Exec.KillSignal),
			KillTimeout:  config.TimeDurationVal(t.Exec.KillTimeout),
			Splay:        config.TimeDurationVal(t.Exec.Splay),
		}); err != nil {
			s := fmt.Sprintf("failed to execute command %q from %s", command, t.Display())
			errs = append(errs, errors.Wrap(err, s))
		}
	}

	// If we got this far and have a child process, we need to send the reload
	// signal to the child process.
	if renderedAny && r.child != nil {
		r.childLock.RLock()
		if err := r.child.Reload(); err != nil {
			errs = append(errs, err)
		}
		r.childLock.RUnlock()
	}

	// If any errors were returned, convert them to an ErrorList for human
	// readability.
	if len(errs) != 0 {
		var result *multierror.Error
		for _, err := range errs {
			result = multierror.Append(result, err)
		}
		return result.ErrorOrNil()
	}

	return nil
}
func (r *Runner) Run() error {
	log.Printf("[DEBUG] (runner) initiating run")

	var newRenderEvent, wouldRenderAny, renderedAny bool
	runCtx := &templateRunCtx{
		depsMap: make(map[string]dep.Dependency),
	}

	for _, tmpl := range r.templates {
		event, err := r.runTemplate(tmpl, runCtx)
		if err != nil {
			return err
		}

		
		if event != nil {
			r.renderEventsLock.Lock()
			r.renderEvents[tmpl.ID()] = event
			r.renderEventsLock.Unlock()

			
			newRenderEvent = true

			
			if event.WouldRender {
				wouldRenderAny = true
			}

			
			if event.DidRender {
				renderedAny = true
			}
		}
	}

	
	if wouldRenderAny || renderedAny {
		
		select {
		case r.renderedCh <- struct{}{}:
		default:
		}
	}

	
	if newRenderEvent {
		select {
		case r.renderEventCh <- struct{}{}:
		default:
		}
	}

	
	r.diffAndUpdateDeps(runCtx.depsMap)

	
	
	var errs []error
	for _, t := range runCtx.commands {
		command := config.StringVal(t.Exec.Command)
		log.Printf("[INFO] (runner) executing command %q from %s", command, t.Display())
		env := t.Exec.Env.Copy()
		env.Custom = append(r.childEnv(), env.Custom...)
		if _, err := spawnChild(&spawnChildInput{
			Stdin:        r.inStream,
			Stdout:       r.outStream,
			Stderr:       r.errStream,
			Command:      command,
			Env:          env.Env(),
			Timeout:      config.TimeDurationVal(t.Exec.Timeout),
			ReloadSignal: config.SignalVal(t.Exec.ReloadSignal),
			KillSignal:   config.SignalVal(t.Exec.KillSignal),
			KillTimeout:  config.TimeDurationVal(t.Exec.KillTimeout),
			Splay:        config.TimeDurationVal(t.Exec.Splay),
		}); err != nil {
			s := fmt.Sprintf("failed to execute command %q from %s", command, t.Display())
			errs = append(errs, errors.Wrap(err, s))
		}
	}

	
	
	if renderedAny && r.child != nil {
		r.childLock.RLock()
		if err := r.child.Reload(); err != nil {
			errs = append(errs, err)
		}
		r.childLock.RUnlock()
	}

	
	
	if len(errs) != 0 {
		var result *multierror.Error
		for _, err := range errs {
			result = multierror.Append(result, err)
		}
		return result.ErrorOrNil()
	}

	return nil
}
func ( r * Runner ) Run ( ) error { log . Printf ( " " ) var newRenderEvent , wouldRenderAny , renderedAny bool runCtx := & templateRunCtx { depsMap : make ( map [ string ] dep . Dependency ) , } for _ , tmpl := range r . templates { event , err := r . runTemplate ( tmpl , runCtx ) if err != nil { return err } // If there was a render event store it if event != nil { r . renderEventsLock . Lock ( ) r . renderEvents [ tmpl . ID ( ) ] = event r . renderEventsLock . Unlock ( ) // Record that there is at least one new render event newRenderEvent = true // Record that at least one template would have been rendered. if event . WouldRender { wouldRenderAny = true } // Record that at least one template was rendered. if event . DidRender { renderedAny = true } } } // Check if we need to deliver any rendered signals if wouldRenderAny || renderedAny { // Send the signal that a template got rendered select { case r . renderedCh <- struct { } { } : default : } } // Check if we need to deliver any event signals if newRenderEvent { select { case r . renderEventCh <- struct { } { } : default : } } // Perform the diff and update the known dependencies. r . diffAndUpdateDeps ( runCtx . depsMap ) // Execute each command in sequence, collecting any errors that occur - this // ensures all commands execute at least once. var errs [ ] error for _ , t := range runCtx . commands { command := config . StringVal ( t . Exec . Command ) log . Printf ( " " , command , t . Display ( ) ) env := t . Exec . Env . Copy ( ) env . Custom = append ( r . childEnv ( ) , env . Custom ... ) if _ , err := spawnChild ( & spawnChildInput { Stdin : r . inStream , Stdout : r . outStream , Stderr : r . errStream , Command : command , Env : env . Env ( ) , Timeout : config . TimeDurationVal ( t . Exec . Timeout ) , ReloadSignal : config . SignalVal ( t . Exec . ReloadSignal ) , KillSignal : config . SignalVal ( t . Exec . KillSignal ) , KillTimeout : config . TimeDurationVal ( t . Exec . KillTimeout ) , Splay : config . TimeDurationVal ( t . Exec . Splay ) , } ) ; err != nil { s := fmt . Sprintf ( " " , command , t . Display ( ) ) errs = append ( errs , errors . Wrap ( err , s ) ) } } // If we got this far and have a child process, we need to send the reload // signal to the child process. if renderedAny && r . child != nil { r . childLock . RLock ( ) if err := r . child . Reload ( ) ; err != nil { errs = append ( errs , err ) } r . childLock . RUnlock ( ) } // If any errors were returned, convert them to an ErrorList for human // readability. if len ( errs ) != 0 { var result * multierror . Error for _ , err := range errs { result = multierror . Append ( result , err ) } return result . ErrorOrNil ( ) } return nil }
// Run iterates over each template in this Runner and conditionally executes
// the template rendering and command execution.
//
// The template is rendered atomically. If and only if the template render
// completes successfully, the optional commands will be executed, if given.
// Please note that all templates are rendered **and then** any commands are
// executed.
Run iterates over each template in this Runner and conditionally executes the template rendering and command execution . The template is rendered atomically . If and only if the template render completes successfully the optional commands will be executed if given . Please note that all templates are rendered ** and then ** any commands are executed .