From 214db1cee36b24143149d545a71493fb71d12a28 Mon Sep 17 00:00:00 2001 From: Christopher Vagnetoft Date: Mon, 21 Mar 2022 00:48:19 +0100 Subject: [PATCH] Misc improvements - Renamed the state file from `fresh.yml` to `.fresh.yml`. - Added option `--state` to override the state file name. - Renamed the lock file from `fresh.lock` to `.fresh.lock`. - Added option `--lockfile` to override lockfile file name. --- CHANGES | 29 +++++++++++++++++++++++++++ README.md | 51 ++++++++++++++++++----------------------------- src/Refresher.php | 51 +++++++++++++++++++++++++++++++++++++++++++---- tools/build.sh | 20 +++++++++++++++++++ 4 files changed, 115 insertions(+), 36 deletions(-) create mode 100644 CHANGES create mode 100755 tools/build.sh diff --git a/CHANGES b/CHANGES new file mode 100644 index 0000000..7d409c4 --- /dev/null +++ b/CHANGES @@ -0,0 +1,29 @@ +# Changelog + +**0.1.1** + +- Moved the logic from the entrypoint script to its own class. +- Added locking (though `fresh.lock` lockfile) to prevent multiple instances. +- Added `--after` hook to invoke script after update. +- Disabled automatic flushing of the state to disk; --check will no longer update + the state file, but --pull and default update will. + +**0.1.2** + +- Fixed a bug in lockfile class preventing release of stale lockfile. +- The `--image` option finally works. +- Added a `--write-state`/`-w` option to write updated hashes to the state file. +- 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. + +**0.1.4** + +- Renamed the state file from `fresh.yml` to `.fresh.yml`. +- Added option `--state` to override the state file name. +- Renamed the lock file from `fresh.lock` to `.fresh.lock`. +- Added option `--lockfile` to override lockfile file name. + diff --git a/README.md b/README.md index ae75389..5717e28 100644 --- a/README.md +++ b/README.md @@ -14,19 +14,24 @@ it can do a combination of things: 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 +## How to install -Build using NoccyLabs Pharlite, included in the tools directory. Don't forget to run -composer to install dependencies first. - - $ composer install - $ tools/pharlite - -## Installing +Fresh requires **PHP 8.0** or later. Download the latest version (or build it yourself) and move it into `/usr/bin`. You can grab it at [https://dev.noccylabs.info/noccy/fresh/releases](https://dev.noccylabs.info/noccy/fresh/releases). +### Building + +Build using NoccyLabs Pharlite, included in the tools directory. Don't forget to run +composer to install dependencies first. In order to properly generate or update the +version file, use the `build.sh` script: + + $ composer install + $ tools/build.sh + +The generated .phar can be found as `fresh.phar` and `dist/fresh-VERSION.phar`. + ## Usage To check for updates, pull updated images and recreate any containers defined in the @@ -50,6 +55,9 @@ Check a specific image: For all available options, use the `--help` flag. +Some of the options can be read from environment variables, for example `FRESH_AFER` +or `FRESH_SLACK`. See `--help` for supported variables. + ## Known Issues - Only checks authenticated registries for new versions. But if you are using @@ -66,29 +74,8 @@ For all available options, use the `--help` flag. - **How do I notify a Mattermost webhook?** Mattermost webhooks are compatible with Slack webhooks, so simply use the `--slack` flag. -## Changes - -**0.1.1** - -- Moved the logic from the entrypoint script to its own class. -- Added locking (though `fresh.lock` lockfile) to prevent multiple instances. -- Added `--after` hook to invoke script after update. -- Disabled automatic flushing of the state to disk; --check will no longer update - the state file, but --pull and default update will. - -**0.1.2** - -- Fixed a bug in lockfile class preventing release of stale lockfile. -- The `--image` option finally works. -- Added a `--write-state`/`-w` option to write updated hashes to the state file. -- 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. - ## Thank you? -You can show your appreciation for the time and sweat you have saved through -Paypal.me: [https://paypal.me/noccy](paypal.me/noccy). +You can show your appreciation by sending me a donation via Paypal.me: +[https://paypal.me/noccy](paypal.me/noccy). + diff --git a/src/Refresher.php b/src/Refresher.php index 2ae3b12..e18f1e8 100644 --- a/src/Refresher.php +++ b/src/Refresher.php @@ -2,6 +2,25 @@ namespace NoccyLabs\FreshDocker; +/* + Fresh.phar + Copyright (C) 2022 NoccyLabs + + 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 . + +*/ + use NoccyLabs\FreshDocker\State\Log; use NoccyLabs\FreshDocker\Configuration\ComposeConfiguration; use NoccyLabs\FreshDocker\Configuration\LocalConfiguration; @@ -16,6 +35,11 @@ use NoccyLabs\FreshDocker\State\Lockfile; class Refresher { + /** + * Map for determining options from command line and environment. Each item + * has the format: + * name => [ short, long, description, [envvar, [default]]] + */ private static array $optionsMap = [ 'General' => [ 'help' => [ 'h', 'help', "Show this help" ], @@ -26,7 +50,7 @@ class Refresher 'pull' => [ null, 'pull', "Only pull if updated, don't up" ], 'check' => [ null, 'check', "Only check for updates, set exit code" ], 'prune' => [ null, 'prune', "Prune dangling images after pull and up" ], - 'write-state' => [ 'w', 'write-state', "Always write updated state (only useful with --check)", false ], + 'write-state' => [ 'w', 'write-state', "Always write updated state (only useful with --check)", null, false ], ], 'Hooks' => [ 'slack' => [ null, 'slack:', "Notify a slack webhook when updating", "FRESH_SLACK" ], @@ -36,10 +60,16 @@ class Refresher 'Config' => [ 'config' => [ 'c:', 'config:', "Use custom configuration file", "FRESH_CONFIG" ], 'config-type' => [ 'C:', 'config-type:', "Configuration type (auto, fresh, compose)", "FRESH_CONFIG_TYPE", "auto" ], + 'state' => [ 's:', 'state:', "Override the state file name", "FRESH_STATE", ".fresh.yml" ], + 'lockfile' => [ 'l:', 'lockfile:', "Override the lockfile file name", "FRESH_LOCKFILE", ".fresh.lock" ], 'credentials' => [ null, 'credentials:', "Set credentials loader type (auto or basic)", "FRESH_CREDENTIALS", "auto" ], ] ]; + private static $StateFileName = ".fresh.yml"; + private static $LockFileName = ".fresh.lock"; + + /** @var array The parsed options */ private array $options = []; /** @var HookInterface[] The hooks to invoke */ @@ -112,6 +142,11 @@ class Refresher } + /** + * Print the usage info (from --help or -h) + * + * + */ public function printUsage() { $tty = posix_isatty(STDOUT); @@ -186,11 +221,13 @@ class Refresher exit(($updated === null) ? 0 : 1); } catch (\Throwable $t) { + fprintf(STDERR, "fatal: %s (%s#%d)\n", $t->getMessage(), $t->getFile(), $t->getLine()); if (!$this->options['verbose']) { fprintf(STDERR, $this->log->asString()."\n"); } exit(2); + } } @@ -210,8 +247,14 @@ class Refresher $this->log->append("Working dir: ".$this->path); chdir($this->path); - $this->state = new PersistentState($this->path . "/fresh.yml"); - $this->lockfile = new Lockfile($this->path . "/fresh.lock"); + $statefile = $this->options['state']; + if (!str_starts_with($statefile,'/')) $statefile = $this->path . "/" . $statefile; + + $lockfile = $this->options['lockfile']; + if (!str_starts_with($lockfile,'/')) $lockfile = $this->path . "/" . $lockfile; + + $this->state = new PersistentState($statefile); // $this->path . "/" . self::$StateFileName); + $this->lockfile = new Lockfile($lockfile); // $this->path . "/" . self::$LockFileName); } /** @@ -224,7 +267,7 @@ class Refresher case 'auto': case 'basic': $this->credentialsLoader = new BasicCredentialsLoader(); - $this->log->append("Using BasicCredentialsLoader for credentials"); + $this->log->append("Using BasicCredentialsLoader"); break; default: fwrite(STDERR, "error: Invalid credentials loader type\n"); diff --git a/tools/build.sh b/tools/build.sh new file mode 100755 index 0000000..55dc025 --- /dev/null +++ b/tools/build.sh @@ -0,0 +1,20 @@ +#!/bin/bash + +# chdir into the root from wherever we are +cd "$(dirname "$(realpath "$0")")/.." + +# determine the tag and output base +TAG="$(git describe --tags)" +OUT="dist/fresh-${TAG}" +NOW="$(date +"%Y-%m-%d")" + +# create output directory +mkdir -p dist + +# update version.php and build thephar +echo " src/version.php +tools/pharlite + +# copy raw phar into destination +cp -v fresh.phar "$OUT.phar" +