Improved hooks and scripts
* Invoke hooks before and after updating * Scripts can now be run --before and --after
This commit is contained in:
		
							
								
								
									
										31
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										31
									
								
								README.md
									
									
									
									
									
								
							@@ -1,7 +1,18 @@
 | 
				
			|||||||
# Fresh: Keeping your docker stacks up to date
 | 
					# Fresh: Keeping your docker stacks up to date
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Fresh was written to scratch an itch. It works by querying the respective repositories
 | 
					Fresh was written to scratch an itch. It works by querying the respective repositories
 | 
				
			||||||
returning
 | 
					for the various manifests in order to determine if the images have been changed. If so
 | 
				
			||||||
 | 
					it can do a combination of things:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- Set the exitcode to indicate the freshness, `0` means up-to-date and `1` outdated.
 | 
				
			||||||
 | 
					- Pull the updated images with docker-compose, and optionally recreate the containers
 | 
				
			||||||
 | 
					  with `docker-compose up`.
 | 
				
			||||||
 | 
					- Run a script before and after updating, f.ex. to enable maintenance mode or update
 | 
				
			||||||
 | 
					  permission on volumes.
 | 
				
			||||||
 | 
					- Notify webhooks when updating. Currently only Slack and Mattermost are supported.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Fresh is designed to be invoked using cron or systemd timers, and as such provides
 | 
				
			||||||
 | 
					a light-weight easy-to-use alternative to more complex toolkits.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Building
 | 
					## Building
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -13,6 +24,8 @@ Build using NoccyLabs Pharlite:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
Download the latest version (or build it yourself) and move it into `/usr/bin`.
 | 
					Download the latest version (or build it yourself) and move it into `/usr/bin`.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Go grab it at [https://dev.noccylabs.info/noccy/fresh/releases](https://dev.noccylabs.info/noccy/fresh/releases)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Usage
 | 
					## Usage
 | 
				
			||||||
 | 
					
 | 
				
			||||||
To check for updates, pull updated images and recreate any containers defined in the
 | 
					To check for updates, pull updated images and recreate any containers defined in the
 | 
				
			||||||
@@ -20,6 +33,15 @@ To check for updates, pull updated images and recreate any containers defined in
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    $ fresh.phar 
 | 
					    $ fresh.phar 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Specify a directory to chdir into; very useful with cron:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $ fresh.phar --dir /srv/docker/mystack
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					To invoke scripts or webhooks:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $ fresh.phar --before scripts/sitedown.sh --after scripts/siteup.sh \
 | 
				
			||||||
 | 
					        --slack https://my.slack.or/mattermost/webhook
 | 
				
			||||||
 | 
					
 | 
				
			||||||
For all available options, use the `--help` flag.
 | 
					For all available options, use the `--help` flag.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Known Issues
 | 
					## Known Issues
 | 
				
			||||||
@@ -37,6 +59,8 @@ For all available options, use the `--help` flag.
 | 
				
			|||||||
- **What are these hashes?** Fresh grabs the manifest for the image from the registry
 | 
					- **What are these hashes?** Fresh grabs the manifest for the image from the registry
 | 
				
			||||||
  and proceeds to hash a concatenation of all the various build layer hashes. This
 | 
					  and proceeds to hash a concatenation of all the various build layer hashes. This
 | 
				
			||||||
  should mean if the image is new but the layers are the same nothing will be updated.
 | 
					  should mean if the image is new but the layers are the same nothing will be updated.
 | 
				
			||||||
 | 
					- **How do I notify a Mattermost webook?** Mattermost webhooks are compatible with
 | 
				
			||||||
 | 
					  Slack webhooks, so simply use the `--slack` flag.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Changes
 | 
					## Changes
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -54,3 +78,8 @@ For all available options, use the `--help` flag.
 | 
				
			|||||||
- The `--image` option finally works.
 | 
					- The `--image` option finally works.
 | 
				
			||||||
- Added a `--write-state`/`-w` option to write updated hashes to the state file.
 | 
					- Added a `--write-state`/`-w` option to write updated hashes to the state file.
 | 
				
			||||||
- Implemented `--config` and `--config-type`options.
 | 
					- Implemented `--config` and `--config-type`options.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					**0.1.3**
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- Added a `--before` script hook, to complement the `--after` hook.
 | 
				
			||||||
 | 
					- Hooks now invoked both before and after deploy.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -30,7 +30,8 @@ class Refresher
 | 
				
			|||||||
        ],
 | 
					        ],
 | 
				
			||||||
        'Hooks' => [
 | 
					        'Hooks' => [
 | 
				
			||||||
            'slack' => [ null, 'slack:', "Notify a slack webhook when updating", "FRESH_SLACK" ],
 | 
					            'slack' => [ null, 'slack:', "Notify a slack webhook when updating", "FRESH_SLACK" ],
 | 
				
			||||||
            'script' => [ null, 'after:', "Invoke script after updating", "FRESH_AFTER" ],
 | 
					            'script-after' => [ null, 'after:', "Invoke script after updating", "FRESH_AFTER" ],
 | 
				
			||||||
 | 
					            'script-before' => [ null, 'before:', "Invoke script before updating", "FRESH_BEFORE" ],
 | 
				
			||||||
        ],
 | 
					        ],
 | 
				
			||||||
        'Config' => [
 | 
					        'Config' => [
 | 
				
			||||||
            'config' => [ 'c:', 'config:', "Use custom configuration file", "FRESH_CONFIG" ],
 | 
					            'config' => [ 'c:', 'config:', "Use custom configuration file", "FRESH_CONFIG" ],
 | 
				
			||||||
@@ -175,9 +176,11 @@ class Refresher
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if ($updated !== null) {
 | 
					            if ($updated !== null) {
 | 
				
			||||||
                $this->callHooks($updated);
 | 
					                $this->callHooks($updated, 'before');
 | 
				
			||||||
                $this->doUpdate($updated);
 | 
					                $this->callScript('before');
 | 
				
			||||||
                $this->callScript();
 | 
					                $this->doUpdate();
 | 
				
			||||||
 | 
					                $this->callHooks($updated, 'after');
 | 
				
			||||||
 | 
					                $this->callScript('after');
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
                
 | 
					                
 | 
				
			||||||
            exit(($updated === null) ? 0 : 1);
 | 
					            exit(($updated === null) ? 0 : 1);
 | 
				
			||||||
@@ -362,13 +365,22 @@ class Refresher
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private function callHooks(array $updated)
 | 
					    private function callHooks(array $updated, string $event)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        $images = [];
 | 
					        switch ($event) {
 | 
				
			||||||
        foreach ($updated as $u) {
 | 
					            case 'before':
 | 
				
			||||||
            $images[] = sprintf("%s/%s:%s", $u->ref->getRegistry(), $u->ref->getImage(), $u->ref->getTag());
 | 
					                $images = [];
 | 
				
			||||||
 | 
					                foreach ($updated as $u) {
 | 
				
			||||||
 | 
					                    $images[] = sprintf("%s/%s:%s", $u->ref->getRegistry(), $u->ref->getImage(), $u->ref->getTag());
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                $msg = "Deploying updated containers:\n* ".join("\n* ", $images);
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            case 'after':
 | 
				
			||||||
 | 
					                $msg = "Deploy complete";
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            default:
 | 
				
			||||||
 | 
					                return;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        $msg = "Deploying updated containers:\n* ".join("\n* ", $images);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        foreach ($this->hooks as $hook) {
 | 
					        foreach ($this->hooks as $hook) {
 | 
				
			||||||
            $hook->sendMessage($msg, []);
 | 
					            $hook->sendMessage($msg, []);
 | 
				
			||||||
@@ -376,9 +388,9 @@ class Refresher
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private function callScript()
 | 
					    private function callScript(string $event)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        $script = $this->options['script'];
 | 
					        $script = $this->options["script-{$event}"] ?? null;
 | 
				
			||||||
        if ($script) {
 | 
					        if ($script) {
 | 
				
			||||||
            $this->exec($script);
 | 
					            $this->exec($script);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user