gowatch

package module
v0.0.0-...-e4443ef Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 17, 2019 License: MIT Imports: 16 Imported by: 0

README

gowatch

Build Status Go Report Card GoDoc

gowatch is both a tool and a library to run both scripts and long-running services (like HTTP servers) in response to file events.

NOTE: The design of the bianry and library of gowatch is not yet finalized and may change in future commits. gowatch should be cross-platform but usage of it has not yet been tested on Windows.

gowatch is driven by a yaml configuration file that tells it:

  1. What scripts will be triggered by file events (called actions)
  2. What long-running services will be run and restarted by file events (called services)
  3. What triggers to run as soon as gowatch boots
  4. Which files to watch and what events should they trigger when they change.

Installing

go get -u github.com/rfratto/gowatch/...

Running

gowatch -c path/to/config.yml

Example configuration file

# A list of actions that we will run. Each action is a bash-like script.
actions:
  vet: |
    echo running go vet...
    go vet ./...
  install: |
    echo running go install...
    go install ./cmd/...
# A list of services that gowatch will keep alive if they exit.
services:
  tick: |
    echo tick
    sleep 1
    echo tock
    sleep 1
# A list of actions and services we wish to trigger when starting gowatch
on_start:
  - tick
# Our list of file patterns. Each file pattern can watch a separate set of
# files and exclude patterns from that set.
file_triggers:
  # Watch all go files in the root directory and all subdirectories, excluding
  # vendor. When any of those files have changed, re-run vet, stop the tick
  # service, re-run install, and restart the tick service. tick:stop is not
  # necessary; omitting tick:stop would restart tick if it was currently running
  # once the noraml tick trigger occurs.
  #
  # If any trigger fails to launch, the whole trigger process will abort.
  - include: ["*.go", "**/*.go", "Gopkg.lock", "Gopkg.toml"]
    exclude: ["vendor/"]
    trigger:
      - vet
      - tick:stop
      - install
      - tick

Documentation

Overview

Package gowatch implements utilities for watching a subset of directories and running sequences of actions when given files change.

The core of gowatch is gowatch.Config, which holds the following:

1. A list of named scripts (actions and services). An action script is something that exits, while a service does not. For example, starting a server is considered a service, since it continues to run in the background. Each script has a name that can be referenced by other parts of the config.

2. A list of scripts to run on startup of gowatch.

3. A list of file triggers. The combined list of file triggers indicate which directories gowatch should watch for file changes.

A file trigger holds the following:

1. The files/directories to include in the trigger.

2. The files/directories to exclude from the included list.

3. The scripts to trigger when a file in the watched list changes.

Include and exclude patterns can be glob expressions to a path relative to the working directory of the gowatch to an absolute path. Glob expressions match * to a directory and ** to any level of subdirectories. For example, src/**/*.js matches any JS file in any subfolder of src.

To have a pattern that only matches against directories, append a / at the end of the pattern. For example, **/ matches all directories.

Relative patterns will match relative to the working directory as defined by gowatch.Watcher. Absolute paths can still be used to watch paths outside of the working directory.

Triggers

When a sequence of scripts is triggered, actions will be fired off and gowatch will wait for them to finish before going to the next script in the sequence. If the script is a service, one of two things will happen: It will be started if it is not currently running, and it will be restarted if it is.

File System Events

File Triggers are collected in batches in case of many files changing at once. Whenever a file change is detected, a 250ms timer starts. All other file changes within that 250ms window will be collected. After that 250ms timer expires, all file updates collected in that batch will be analyzed and the proper triggers will fire.

Trigger Priority

Triggers run in the order as defined in the trigger list. If multiple file_triggers match, the actions and services will be ran in definition order with duplicates removed. Each action will be run to completion before the next one is started.

Trigger Cancellation

If another trigger event occurs while one or more triggers is queued up to run, then the queue will be cancelled and the running trigger will be aborted.

Here is an example configuration YAML file for a NodeJS project that uses gulp:

actions:
  install: npm i
  build: gulp build
services:
  run: gulp start
on_start:
  - install
  - build
  - run
file_triggers:
  - include: ["/tmp/cache.lock"]
    trigger:
      - build
      - run
    exclude: ["node_modules/", "build/", "package.json", "package-lock.json"]
    trigger:
      - build
      - run
  - include:
      - package.json
      - package-lock.json
    trigger:
      - install
      - build
      - run

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Config

type Config struct {
	// Actions is a named list of oneshot scripts.
	Actions map[string]string `yaml:"actions"`

	// Services is a named list of long-running scripts that are intended to not exit.
	Services map[string]string `yaml:"services"`

	// StartupSteps holds the list of actions and services to run on start.
	StartupSteps []string `yaml:"on_start"`

	// FileTriggers holds a list of file events to watch for and a list of
	// scripts to execute when a matching event occurs. This is a sorted list;
	// earlier triggers are treated as higher precedence and will execute
	// first.
	FileTriggers []FileTrigger `yaml:"file_triggers"`
}

Config holds the configuration for the directory tree that will be watched and the scripts that will be ran on it.

type FileTrigger

type FileTrigger struct {
	// Include holds patterns to include when checking if the file trigger
	// is activated. A * matches all files.
	Include []string `yaml:"include"`

	// Exclude holds patterns to ignore when checking if the file trigger
	// is activated.
	Exclude []string `yaml:"exclude"`

	// Triggers holds the list of scripts and services to trigger when the
	// file trigger is detected.
	Triggers []string `yaml:"trigger"`
}

A FileTrigger is a pattern of whitelisted and blacklisted files that will invoke a series of steps when a file within the watched list changes.

func (*FileTrigger) Matches

func (t *FileTrigger) Matches(root string, path string) bool

Matches takes an path to a file and returns whether or not that path is included in the current trigger.

type Watcher

type Watcher struct {
	// Working directory to watch
	Directory string

	// The writer for debug output to go to.
	Debug io.Writer

	// The writer for triggers to write output to
	Stdout io.Writer

	// The writer for triggers to write errors to
	Stderr io.Writer

	// Config of file triggers and events to run
	Config Config
	// contains filtered or unexported fields
}

Watcher is the instance of the watcher itself. It holds the configuration for the directory tree to be watched and the root directory to watch.

func NewWatcher

func NewWatcher(dir string, config Config) *Watcher

NewWatcher returns a new Watcher given a directory to watch and a config with file patterns and triggers.

func NewWatcherWithContext

func NewWatcherWithContext(ctx context.Context, dir string, config Config) *Watcher

NewWatcherWithContext returns a new Watcher given a directory to watch and a config with file patterns and triggers. It accepts a context that, when the watcher is started, allows for cancellation.

func (*Watcher) MatchingTriggers

func (w *Watcher) MatchingTriggers(path string) (triggers []FileTrigger, err error)

MatchingTriggers takes a full path to a file and returns all trigers that match that path.

func (*Watcher) Run

func (w *Watcher) Run(ctx context.Context, trigger string) error

Run runs a specific named trigger defined from the watcher's config. The trigger can either be a service or an action.

func (*Watcher) Start

func (w *Watcher) Start() error

Start starts the watcher. Start should not exit normally unless an error occurred or the watcher is cancelled through the context passed to NewWatchWithContext.

func (*Watcher) Validate

func (w *Watcher) Validate() error

Validate validates the configuration file and returns any errors.

func (*Watcher) WatchedPaths

func (w *Watcher) WatchedPaths() []string

WatchedPaths returns the list of files and directories that will be monitored by the watcher. Each path is the absolute path on disk.

Directories

Path Synopsis
cmd
gowatch
Command gowatch is a tool for running services and tasks triggered by filesystem changes.
Command gowatch is a tool for running services and tasks triggered by filesystem changes.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL