From d2fce25924d6a7db649de045ba039a036f008a63 Mon Sep 17 00:00:00 2001 From: Salamandar <6552989+Salamandar@users.noreply.github.com> Date: Mon, 2 Oct 2023 13:41:27 +0200 Subject: [PATCH] Initial commit for Woodpecker --- LICENSE | 23 +- README.md | 41 ++-- README_fr.md | 30 ++- conf/nginx.conf | 30 +-- conf/php-fpm.conf | 430 --------------------------------- conf/systemd.service | 5 +- conf/woodpecker-server.conf | 153 ++++++++++++ doc/POST_INSTALL.md | 7 - doc/POST_UPGRADE.md | 1 - doc/PRE_INSTALL.md | 4 +- doc/PRE_INSTALL_fr.md | 4 +- doc/PRE_UPGRADE.md | 1 - doc/screenshots/example.jpg | Bin 35451 -> 0 bytes doc/screenshots/woodpecker.png | Bin 0 -> 71639 bytes manifest.toml | 155 ++++++------ scripts/_common.sh | 13 + scripts/backup | 35 +-- scripts/install | 117 +-------- scripts/remove | 31 +-- scripts/restore | 39 +-- scripts/upgrade | 59 +---- tests.toml | 29 +++ tests.toml.example | 67 ----- 23 files changed, 369 insertions(+), 905 deletions(-) delete mode 100644 conf/php-fpm.conf create mode 100644 conf/woodpecker-server.conf delete mode 100644 doc/POST_INSTALL.md delete mode 100644 doc/POST_UPGRADE.md delete mode 100644 doc/PRE_UPGRADE.md delete mode 100644 doc/screenshots/example.jpg create mode 100644 doc/screenshots/woodpecker.png create mode 100644 tests.toml delete mode 100644 tests.toml.example diff --git a/LICENSE b/LICENSE index 2026412..745c7c4 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,21 @@ -File containing the license of your package. +The MIT License (MIT) -More information here: -https://choosealicense.com/ +Copyright (c) 2015 mbugeia + +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. diff --git a/README.md b/README.md index faf15f6..e5e77c3 100644 --- a/README.md +++ b/README.md @@ -1,28 +1,17 @@ -# Packaging an app, starting from this example - -* Copy this app before working on it, using the ['Use this template'](https://github.com/YunoHost/example_ynh/generate) button on the Github repo. -* Edit the `manifest.json` with app specific info. -* Edit the `install`, `upgrade`, `remove`, `backup`, and `restore` scripts, and any relevant conf files in `conf/`. - * Using the [script helpers documentation.](https://yunohost.org/packaging_apps_helpers) -* Add a `LICENSE` file for the package. -* Edit `doc/DISCLAIMER*.md` -* The `README.md` files are to be automatically generated by https://github.com/YunoHost/apps/tree/master/tools/README-generator - ---- -# Example app for YunoHost +# Woodpecker for YunoHost -[![Integration level](https://dash.yunohost.org/integration/example.svg)](https://dash.yunohost.org/appci/app/example) ![Working status](https://ci-apps.yunohost.org/ci/badges/example.status.svg) ![Maintenance status](https://ci-apps.yunohost.org/ci/badges/example.maintain.svg) +[![Integration level](https://dash.yunohost.org/integration/woodpecker.svg)](https://dash.yunohost.org/appci/app/woodpecker) ![Working status](https://ci-apps.yunohost.org/ci/badges/woodpecker.status.svg) ![Maintenance status](https://ci-apps.yunohost.org/ci/badges/woodpecker.maintain.svg) -[![Install Example app with YunoHost](https://install-app.yunohost.org/install-with-yunohost.svg)](https://install-app.yunohost.org/?app=example) +[![Install Woodpecker with YunoHost](https://install-app.yunohost.org/install-with-yunohost.svg)](https://install-app.yunohost.org/?app=woodpecker) *[Lire ce readme en français.](./README_fr.md)* -> *This package allows you to install Example app quickly and simply on a YunoHost server. +> *This package allows you to install Woodpecker quickly and simply on a YunoHost server. If you don't have YunoHost, please consult [the guide](https://yunohost.org/#/install) to learn how to install it.* ## Overview @@ -30,32 +19,30 @@ If you don't have YunoHost, please consult [the guide](https://yunohost.org/#/in This is a dummy description of this app features -**Shipped version:** 1.0~ynh1 - -**Demo:** https://demo.example.com +**Shipped version:** 1.0.2~ynh1 ## Screenshots -![Screenshot of Example app](./doc/screenshots/example.jpg) +![Screenshot of Woodpecker](./doc/screenshots/woodpecker.png) ## Documentation and resources -* Official app website: -* Official user documentation: -* Official admin documentation: -* Upstream app code repository: -* Report a bug: +* Official app website: +* Official user documentation: +* Official admin documentation: +* Upstream app code repository: +* Report a bug: ## Developer info -Please send your pull request to the [testing branch](https://github.com/YunoHost-Apps/example_ynh/tree/testing). +Please send your pull request to the [testing branch](https://github.com/YunoHost-Apps/woodpecker_ynh/tree/testing). To try the testing branch, please proceed like that. ``` bash -sudo yunohost app install https://github.com/YunoHost-Apps/example_ynh/tree/testing --debug +sudo yunohost app install https://github.com/YunoHost-Apps/woodpecker_ynh/tree/testing --debug or -sudo yunohost app upgrade example -u https://github.com/YunoHost-Apps/example_ynh/tree/testing --debug +sudo yunohost app upgrade woodpecker -u https://github.com/YunoHost-Apps/woodpecker_ynh/tree/testing --debug ``` **More info regarding app packaging:** diff --git a/README_fr.md b/README_fr.md index ae35cbc..4cb831a 100644 --- a/README_fr.md +++ b/README_fr.md @@ -3,15 +3,15 @@ N.B.: This README was automatically generated by https://github.com/YunoHost/app It shall NOT be edited by hand. --> -# Example app pour YunoHost +# Woodpecker pour YunoHost -[![Niveau d’intégration](https://dash.yunohost.org/integration/example.svg)](https://dash.yunohost.org/appci/app/example) ![Statut du fonctionnement](https://ci-apps.yunohost.org/ci/badges/example.status.svg) ![Statut de maintenance](https://ci-apps.yunohost.org/ci/badges/example.maintain.svg) +[![Niveau d’intégration](https://dash.yunohost.org/integration/woodpecker.svg)](https://dash.yunohost.org/appci/app/woodpecker) ![Statut du fonctionnement](https://ci-apps.yunohost.org/ci/badges/woodpecker.status.svg) ![Statut de maintenance](https://ci-apps.yunohost.org/ci/badges/woodpecker.maintain.svg) -[![Installer Example app avec YunoHost](https://install-app.yunohost.org/install-with-yunohost.svg)](https://install-app.yunohost.org/?app=example) +[![Installer Woodpecker avec YunoHost](https://install-app.yunohost.org/install-with-yunohost.svg)](https://install-app.yunohost.org/?app=woodpecker) *[Read this readme in english.](./README.md)* -> *Ce package vous permet d’installer Example app rapidement et simplement sur un serveur YunoHost. +> *Ce package vous permet d’installer Woodpecker rapidement et simplement sur un serveur YunoHost. Si vous n’avez pas YunoHost, regardez [ici](https://yunohost.org/#/install) pour savoir comment l’installer et en profiter.* ## Vue d’ensemble @@ -19,32 +19,30 @@ Si vous n’avez pas YunoHost, regardez [ici](https://yunohost.org/#/install) po Ceci est une fausse description des fonctionalités de l'app -**Version incluse :** 1.0~ynh1 - -**Démo :** https://demo.example.com +**Version incluse :** 1.0.2~ynh1 ## Captures d’écran -![Capture d’écran de Example app](./doc/screenshots/example.jpg) +![Capture d’écran de Woodpecker](./doc/screenshots/woodpecker.png) ## Documentations et ressources -* Site officiel de l’app : -* Documentation officielle utilisateur : -* Documentation officielle de l’admin : -* Dépôt de code officiel de l’app : -* Signaler un bug : +* Site officiel de l’app : +* Documentation officielle utilisateur : +* Documentation officielle de l’admin : +* Dépôt de code officiel de l’app : +* Signaler un bug : ## Informations pour les développeurs -Merci de faire vos pull request sur la [branche testing](https://github.com/YunoHost-Apps/example_ynh/tree/testing). +Merci de faire vos pull request sur la [branche testing](https://github.com/YunoHost-Apps/woodpecker_ynh/tree/testing). Pour essayer la branche testing, procédez comme suit. ``` bash -sudo yunohost app install https://github.com/YunoHost-Apps/example_ynh/tree/testing --debug +sudo yunohost app install https://github.com/YunoHost-Apps/woodpecker_ynh/tree/testing --debug ou -sudo yunohost app upgrade example -u https://github.com/YunoHost-Apps/example_ynh/tree/testing --debug +sudo yunohost app upgrade woodpecker -u https://github.com/YunoHost-Apps/woodpecker_ynh/tree/testing --debug ``` **Plus d’infos sur le packaging d’applications :** \ No newline at end of file diff --git a/conf/nginx.conf b/conf/nginx.conf index 86f404e..7c8005b 100644 --- a/conf/nginx.conf +++ b/conf/nginx.conf @@ -1,28 +1,18 @@ #sub_path_only rewrite ^__PATH__$ __PATH__/ permanent; location __PATH__/ { - # Path to source - alias __INSTALL_DIR__/; + proxy_set_header X-Forwarded-For $remote_addr; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header Host $host; -### Example PHP configuration (remove it if not used) - index index.php; + proxy_pass http://127.0.0.1:__PORT__; + proxy_redirect off; + proxy_http_version 1.1; + proxy_buffering off; - # Common parameter to increase upload size limit in conjunction with dedicated php-fpm file - #client_max_body_size 50M; - - try_files $uri $uri/ index.php; - location ~ [^/]\.php(/|$) { - fastcgi_split_path_info ^(.+?\.php)(/.*)$; - fastcgi_pass unix:/var/run/php/php__PHPVERSION__-fpm-__NAME__.sock; - - fastcgi_index index.php; - include fastcgi_params; - fastcgi_param REMOTE_USER $remote_user; - fastcgi_param PATH_INFO $fastcgi_path_info; - fastcgi_param SCRIPT_FILENAME $request_filename; - } -### End of PHP configuration part + chunked_transfer_encoding off; # Include SSOWAT user panel. - include conf.d/yunohost_panel.conf.inc; + # Looks like this breaks registration into woodpecker… + # include conf.d/yunohost_panel.conf.inc; } diff --git a/conf/php-fpm.conf b/conf/php-fpm.conf deleted file mode 100644 index 13a53b0..0000000 --- a/conf/php-fpm.conf +++ /dev/null @@ -1,430 +0,0 @@ -; Start a new pool named 'www'. -; the variable $pool can be used in any directive and will be replaced by the -; pool name ('www' here) -[__NAMETOCHANGE__] - -; Per pool prefix -; It only applies on the following directives: -; - 'access.log' -; - 'slowlog' -; - 'listen' (unixsocket) -; - 'chroot' -; - 'chdir' -; - 'php_values' -; - 'php_admin_values' -; When not set, the global prefix (or /usr) applies instead. -; Note: This directive can also be relative to the global prefix. -; Default Value: none -;prefix = /path/to/pools/$pool - -; Unix user/group of processes -; Note: The user is mandatory. If the group is not set, the default user's group -; will be used. -user = __USER__ -group = __USER__ - -; The address on which to accept FastCGI requests. -; Valid syntaxes are: -; 'ip.add.re.ss:port' - to listen on a TCP socket to a specific IPv4 address on -; a specific port; -; '[ip:6:addr:ess]:port' - to listen on a TCP socket to a specific IPv6 address on -; a specific port; -; 'port' - to listen on a TCP socket to all addresses -; (IPv6 and IPv4-mapped) on a specific port; -; '/path/to/unix/socket' - to listen on a unix socket. -; Note: This value is mandatory. -listen = /var/run/php/php__PHPVERSION__-fpm-__NAMETOCHANGE__.sock - -; Set listen(2) backlog. -; Default Value: 511 (-1 on FreeBSD and OpenBSD) -;listen.backlog = 511 - -; Set permissions for unix socket, if one is used. In Linux, read/write -; permissions must be set in order to allow connections from a web server. Many -; BSD-derived systems allow connections regardless of permissions. -; Default Values: user and group are set as the running user -; mode is set to 0660 -listen.owner = www-data -listen.group = www-data -;listen.mode = 0660 -; When POSIX Access Control Lists are supported you can set them using -; these options, value is a comma separated list of user/group names. -; When set, listen.owner and listen.group are ignored -;listen.acl_users = -;listen.acl_groups = - -; List of addresses (IPv4/IPv6) of FastCGI clients which are allowed to connect. -; Equivalent to the FCGI_WEB_SERVER_ADDRS environment variable in the original -; PHP FCGI (5.2.2+). Makes sense only with a tcp listening socket. Each address -; must be separated by a comma. If this value is left blank, connections will be -; accepted from any ip address. -; Default Value: any -;listen.allowed_clients = 127.0.0.1 - -; Specify the nice(2) priority to apply to the pool processes (only if set) -; The value can vary from -19 (highest priority) to 20 (lower priority) -; Note: - It will only work if the FPM master process is launched as root -; - The pool processes will inherit the master process priority -; unless it specified otherwise -; Default Value: no set -; process.priority = -19 - -; Set the process dumpable flag (PR_SET_DUMPABLE prctl) even if the process user -; or group is differrent than the master process user. It allows to create process -; core dump and ptrace the process for the pool user. -; Default Value: no -; process.dumpable = yes - -; Choose how the process manager will control the number of child processes. -; Possible Values: -; static - a fixed number (pm.max_children) of child processes; -; dynamic - the number of child processes are set dynamically based on the -; following directives. With this process management, there will be -; always at least 1 children. -; pm.max_children - the maximum number of children that can -; be alive at the same time. -; pm.start_servers - the number of children created on startup. -; pm.min_spare_servers - the minimum number of children in 'idle' -; state (waiting to process). If the number -; of 'idle' processes is less than this -; number then some children will be created. -; pm.max_spare_servers - the maximum number of children in 'idle' -; state (waiting to process). If the number -; of 'idle' processes is greater than this -; number then some children will be killed. -; ondemand - no children are created at startup. Children will be forked when -; new requests will connect. The following parameter are used: -; pm.max_children - the maximum number of children that -; can be alive at the same time. -; pm.process_idle_timeout - The number of seconds after which -; an idle process will be killed. -; Note: This value is mandatory. -pm = dynamic - -; The number of child processes to be created when pm is set to 'static' and the -; maximum number of child processes when pm is set to 'dynamic' or 'ondemand'. -; This value sets the limit on the number of simultaneous requests that will be -; served. Equivalent to the ApacheMaxClients directive with mpm_prefork. -; Equivalent to the PHP_FCGI_CHILDREN environment variable in the original PHP -; CGI. The below defaults are based on a server without much resources. Don't -; forget to tweak pm.* to fit your needs. -; Note: Used when pm is set to 'static', 'dynamic' or 'ondemand' -; Note: This value is mandatory. -pm.max_children = 5 - -; The number of child processes created on startup. -; Note: Used only when pm is set to 'dynamic' -; Default Value: min_spare_servers + (max_spare_servers - min_spare_servers) / 2 -pm.start_servers = 2 - -; The desired minimum number of idle server processes. -; Note: Used only when pm is set to 'dynamic' -; Note: Mandatory when pm is set to 'dynamic' -pm.min_spare_servers = 1 - -; The desired maximum number of idle server processes. -; Note: Used only when pm is set to 'dynamic' -; Note: Mandatory when pm is set to 'dynamic' -pm.max_spare_servers = 3 - -; The number of seconds after which an idle process will be killed. -; Note: Used only when pm is set to 'ondemand' -; Default Value: 10s -;pm.process_idle_timeout = 10s; - -; The number of requests each child process should execute before respawning. -; This can be useful to work around memory leaks in 3rd party libraries. For -; endless request processing specify '0'. Equivalent to PHP_FCGI_MAX_REQUESTS. -; Default Value: 0 -;pm.max_requests = 500 - -; The URI to view the FPM status page. If this value is not set, no URI will be -; recognized as a status page. It shows the following informations: -; pool - the name of the pool; -; process manager - static, dynamic or ondemand; -; start time - the date and time FPM has started; -; start since - number of seconds since FPM has started; -; accepted conn - the number of request accepted by the pool; -; listen queue - the number of request in the queue of pending -; connections (see backlog in listen(2)); -; max listen queue - the maximum number of requests in the queue -; of pending connections since FPM has started; -; listen queue len - the size of the socket queue of pending connections; -; idle processes - the number of idle processes; -; active processes - the number of active processes; -; total processes - the number of idle + active processes; -; max active processes - the maximum number of active processes since FPM -; has started; -; max children reached - number of times, the process limit has been reached, -; when pm tries to start more children (works only for -; pm 'dynamic' and 'ondemand'); -; Value are updated in real time. -; Example output: -; pool: www -; process manager: static -; start time: 01/Jul/2011:17:53:49 +0200 -; start since: 62636 -; accepted conn: 190460 -; listen queue: 0 -; max listen queue: 1 -; listen queue len: 42 -; idle processes: 4 -; active processes: 11 -; total processes: 15 -; max active processes: 12 -; max children reached: 0 -; -; By default the status page output is formatted as text/plain. Passing either -; 'html', 'xml' or 'json' in the query string will return the corresponding -; output syntax. Example: -; http://www.foo.bar/status -; http://www.foo.bar/status?json -; http://www.foo.bar/status?html -; http://www.foo.bar/status?xml -; -; By default the status page only outputs short status. Passing 'full' in the -; query string will also return status for each pool process. -; Example: -; http://www.foo.bar/status?full -; http://www.foo.bar/status?json&full -; http://www.foo.bar/status?html&full -; http://www.foo.bar/status?xml&full -; The Full status returns for each process: -; pid - the PID of the process; -; state - the state of the process (Idle, Running, ...); -; start time - the date and time the process has started; -; start since - the number of seconds since the process has started; -; requests - the number of requests the process has served; -; request duration - the duration in µs of the requests; -; request method - the request method (GET, POST, ...); -; request URI - the request URI with the query string; -; content length - the content length of the request (only with POST); -; user - the user (PHP_AUTH_USER) (or '-' if not set); -; script - the main script called (or '-' if not set); -; last request cpu - the %cpu the last request consumed -; it's always 0 if the process is not in Idle state -; because CPU calculation is done when the request -; processing has terminated; -; last request memory - the max amount of memory the last request consumed -; it's always 0 if the process is not in Idle state -; because memory calculation is done when the request -; processing has terminated; -; If the process is in Idle state, then informations are related to the -; last request the process has served. Otherwise informations are related to -; the current request being served. -; Example output: -; ************************ -; pid: 31330 -; state: Running -; start time: 01/Jul/2011:17:53:49 +0200 -; start since: 63087 -; requests: 12808 -; request duration: 1250261 -; request method: GET -; request URI: /test_mem.php?N=10000 -; content length: 0 -; user: - -; script: /home/fat/web/docs/php/test_mem.php -; last request cpu: 0.00 -; last request memory: 0 -; -; Note: There is a real-time FPM status monitoring sample web page available -; It's available in: /usr/share/php/7.0/fpm/status.html -; -; Note: The value must start with a leading slash (/). The value can be -; anything, but it may not be a good idea to use the .php extension or it -; may conflict with a real PHP file. -; Default Value: not set -;pm.status_path = /status - -; The ping URI to call the monitoring page of FPM. If this value is not set, no -; URI will be recognized as a ping page. This could be used to test from outside -; that FPM is alive and responding, or to -; - create a graph of FPM availability (rrd or such); -; - remove a server from a group if it is not responding (load balancing); -; - trigger alerts for the operating team (24/7). -; Note: The value must start with a leading slash (/). The value can be -; anything, but it may not be a good idea to use the .php extension or it -; may conflict with a real PHP file. -; Default Value: not set -;ping.path = /ping - -; This directive may be used to customize the response of a ping request. The -; response is formatted as text/plain with a 200 response code. -; Default Value: pong -;ping.response = pong - -; The access log file -; Default: not set -;access.log = log/$pool.access.log - -; The access log format. -; The following syntax is allowed -; %%: the '%' character -; %C: %CPU used by the request -; it can accept the following format: -; - %{user}C for user CPU only -; - %{system}C for system CPU only -; - %{total}C for user + system CPU (default) -; %d: time taken to serve the request -; it can accept the following format: -; - %{seconds}d (default) -; - %{miliseconds}d -; - %{mili}d -; - %{microseconds}d -; - %{micro}d -; %e: an environment variable (same as $_ENV or $_SERVER) -; it must be associated with embraces to specify the name of the env -; variable. Some exemples: -; - server specifics like: %{REQUEST_METHOD}e or %{SERVER_PROTOCOL}e -; - HTTP headers like: %{HTTP_HOST}e or %{HTTP_USER_AGENT}e -; %f: script filename -; %l: content-length of the request (for POST request only) -; %m: request method -; %M: peak of memory allocated by PHP -; it can accept the following format: -; - %{bytes}M (default) -; - %{kilobytes}M -; - %{kilo}M -; - %{megabytes}M -; - %{mega}M -; %n: pool name -; %o: output header -; it must be associated with embraces to specify the name of the header: -; - %{Content-Type}o -; - %{X-Powered-By}o -; - %{Transfert-Encoding}o -; - .... -; %p: PID of the child that serviced the request -; %P: PID of the parent of the child that serviced the request -; %q: the query string -; %Q: the '?' character if query string exists -; %r: the request URI (without the query string, see %q and %Q) -; %R: remote IP address -; %s: status (response code) -; %t: server time the request was received -; it can accept a strftime(3) format: -; %d/%b/%Y:%H:%M:%S %z (default) -; The strftime(3) format must be encapsuled in a %{}t tag -; e.g. for a ISO8601 formatted timestring, use: %{%Y-%m-%dT%H:%M:%S%z}t -; %T: time the log has been written (the request has finished) -; it can accept a strftime(3) format: -; %d/%b/%Y:%H:%M:%S %z (default) -; The strftime(3) format must be encapsuled in a %{}t tag -; e.g. for a ISO8601 formatted timestring, use: %{%Y-%m-%dT%H:%M:%S%z}t -; %u: remote user -; -; Default: "%R - %u %t \"%m %r\" %s" -;access.format = "%R - %u %t \"%m %r%Q%q\" %s %f %{mili}d %{kilo}M %C%%" - -; The log file for slow requests -; Default Value: not set -; Note: slowlog is mandatory if request_slowlog_timeout is set -;slowlog = log/$pool.log.slow - -; The timeout for serving a single request after which a PHP backtrace will be -; dumped to the 'slowlog' file. A value of '0s' means 'off'. -; Available units: s(econds)(default), m(inutes), h(ours), or d(ays) -; Default Value: 0 -;request_slowlog_timeout = 0 - -; The timeout for serving a single request after which the worker process will -; be killed. This option should be used when the 'max_execution_time' ini option -; does not stop script execution for some reason. A value of '0' means 'off'. -; Available units: s(econds)(default), m(inutes), h(ours), or d(ays) -; Default Value: 0 -request_terminate_timeout = 1d - -; Set open file descriptor rlimit. -; Default Value: system defined value -;rlimit_files = 1024 - -; Set max core size rlimit. -; Possible Values: 'unlimited' or an integer greater or equal to 0 -; Default Value: system defined value -;rlimit_core = 0 - -; Chroot to this directory at the start. This value must be defined as an -; absolute path. When this value is not set, chroot is not used. -; Note: you can prefix with '$prefix' to chroot to the pool prefix or one -; of its subdirectories. If the pool prefix is not set, the global prefix -; will be used instead. -; Note: chrooting is a great security feature and should be used whenever -; possible. However, all PHP paths will be relative to the chroot -; (error_log, sessions.save_path, ...). -; Default Value: not set -;chroot = - -; Chdir to this directory at the start. -; Note: relative path can be used. -; Default Value: current directory or / when chroot -chdir = __INSTALL_DIR__ - -; Redirect worker stdout and stderr into main error log. If not set, stdout and -; stderr will be redirected to /dev/null according to FastCGI specs. -; Note: on highloaded environement, this can cause some delay in the page -; process time (several ms). -; Default Value: no -;catch_workers_output = yes - -; Clear environment in FPM workers -; Prevents arbitrary environment variables from reaching FPM worker processes -; by clearing the environment in workers before env vars specified in this -; pool configuration are added. -; Setting to "no" will make all environment variables available to PHP code -; via getenv(), $_ENV and $_SERVER. -; Default Value: yes -;clear_env = no - -; Limits the extensions of the main script FPM will allow to parse. This can -; prevent configuration mistakes on the web server side. You should only limit -; FPM to .php extensions to prevent malicious users to use other extensions to -; execute php code. -; Note: set an empty value to allow all extensions. -; Default Value: .php -;security.limit_extensions = .php .php3 .php4 .php5 .php7 - -; Pass environment variables like LD_LIBRARY_PATH. All $VARIABLEs are taken from -; the current environment. -; Default Value: clean env -;env[HOSTNAME] = $HOSTNAME -;env[PATH] = /usr/local/bin:/usr/bin:/bin -;env[TMP] = /tmp -;env[TMPDIR] = /tmp -;env[TEMP] = /tmp - -; Additional php.ini defines, specific to this pool of workers. These settings -; overwrite the values previously defined in the php.ini. The directives are the -; same as the PHP SAPI: -; php_value/php_flag - you can set classic ini defines which can -; be overwritten from PHP call 'ini_set'. -; php_admin_value/php_admin_flag - these directives won't be overwritten by -; PHP call 'ini_set' -; For php_*flag, valid values are on, off, 1, 0, true, false, yes or no. - -; Defining 'extension' will load the corresponding shared extension from -; extension_dir. Defining 'disable_functions' or 'disable_classes' will not -; overwrite previously defined php.ini values, but will append the new value -; instead. - -; Note: path INI options can be relative and will be expanded with the prefix -; (pool, global or /usr) - -; Default Value: nothing is defined by default except the values in php.ini and -; specified at startup with the -d argument -;php_admin_value[sendmail_path] = /usr/sbin/sendmail -t -i -f www@my.domain.com -;php_flag[display_errors] = off -;php_admin_value[error_log] = /var/log/fpm-php.www.log -;php_admin_flag[log_errors] = on -;php_admin_value[memory_limit] = 32M - -; Common values to change to increase file upload limit -; php_admin_value[upload_max_filesize] = 50M -; php_admin_value[post_max_size] = 50M -; php_admin_flag[mail.add_x_header] = Off - -; Other common parameters -; php_admin_value[max_execution_time] = 600 -; php_admin_value[max_input_time] = 300 -; php_admin_value[memory_limit] = 256M -; php_admin_flag[short_open_tag] = On diff --git a/conf/systemd.service b/conf/systemd.service index f100e84..6a62ec9 100644 --- a/conf/systemd.service +++ b/conf/systemd.service @@ -1,5 +1,5 @@ [Unit] -Description=Small description of the service +Description=Woodpecker CI server After=network.target [Service] @@ -7,7 +7,8 @@ Type=simple User=__APP__ Group=__APP__ WorkingDirectory=__INSTALL_DIR__/ -ExecStart=__INSTALL_DIR__/script +ExecStart=__INSTALL_DIR__/woodpecker-server +EnvironmentFile=__INSTALL_DIR__/woodpecker-server.conf StandardOutput=append:/var/log/__APP__/__APP__.log StandardError=inherit diff --git a/conf/woodpecker-server.conf b/conf/woodpecker-server.conf new file mode 100644 index 0000000..d6ad5cf --- /dev/null +++ b/conf/woodpecker-server.conf @@ -0,0 +1,153 @@ +# Taken from https://aur.archlinux.org/cgit/aur.git/plain/woodpecker.conf?h=woodpecker + +# Note that this is not all of the possible configuration options, just the most likely to be used ones. +# View all of the administration documentation here: https://woodpecker-ci.org/docs/administration/server-config +# For integrating with Gitea/Github/Gitlab, look at https://woodpecker-ci.org/docs/administration/vcs/overview + +# Configures the logging level. Possible values are trace, debug, info, warn, error, fatal, panic, disabled and empty. +# Default: empty +#WOODPECKER_LOG_LEVEL= + +# Enable pretty-printed debug output. +# Default: false +WOODPECKER_DEBUG_PRETTY=true + +# Disable colored debug output. +# Default: true +#WOODPECKER_DEBUG_NOCOLOR= + +# Server fully qualified url of the user-facing hostname. +# Default: empty +# Example: WOODPECKER_HOST=http://woodpecker.example.org +WOODPECKER_HOST=https://__DOMAIN____PATH_NO_TRAILING_SLASH__ + +# Configures the HTTP listener port. +# Default: :8000 +WOODPECKER_SERVER_ADDR=:__PORT__ + +# Path to an SSL certificate used by the server to accept HTTPS requests. +# Default: empty +# Example: WOODPECKER_SERVER_CERT=/path/to/cert.pem +#WOODPECKER_SERVER_CERT= + +# Path to an SSL certificate key used by the server to accept HTTPS requests. +# Default: empty +# Example: WOODPECKER_SERVER_KEY=/path/to/key.pem +#WOODPECKER_SERVER_KEY= + +# Automatically generates an SSL certificate using Let's Encrypt, and configures the server to accept HTTPS requests. +# Default: false +#WOODPECKER_LETS_ENCRYPT= + +# Configures the gRPC listener port. +# Default: :9000 +#WOODPECKER_GRPC_ADDR= + +# Comma-separated list of admin accounts. +# Default: empty +# Example: WOODPECKER_ADMIN=user1,user2 +#WOODPECKER_ADMIN= + +# Comma-separated list of approved organizations. +# Default: empty +# Example: org1,org2 +#WOODPECKER_ORGS= + +# Comma-separated list of syncable repo owners. ??? +# Default: empty +# Example: user1,user2 +#WOODPECKER_REPO_OWNERS= + +# Enable to allow user registration. +# Default: false +#WOODPECKER_OPEN= + +# Link to documentation in the UI. +# Default: https://woodpecker-ci.org/ +#WOODPECKER_DOCS= + +# Always use authentication to clone repositories even if they are public. Needed if the SCM requires to always authenticate as used by many companies. +# Default: false +#WOODPECKER_AUTHENTICATE_PUBLIC_REPOS= + +# The default docker image to be used when cloning the repo +# Default: woodpeckerci/plugin-git:latest +#WOODPECKER_DEFAULT_CLONE_IMAGE= + +# Configures the session expiration time. +# Default: 72h +#WOODPECKER_SESSION_EXPIRES= + +# Docker images to run in privileged mode. Only change if you are sure what you do! +# Default: plugins/docker,plugins/gcr,plugins/ecr,woodpeckerci/plugin-docker,woodpeckerci/plugin-docker-buildx +#WOODPECKER_ESCALATE= + +# Configures a specific private registry config for all pipelines. +# Default: empty +# Example: WOODPECKER_DOCKER_CONFIG=/home/user/.docker/config.json +#WOODPECKER_DOCKER_CONFIG= + +# A shared secret used by server and agents to authenticate communication. A secret can be generated by openssl rand -hex 32. +# Default: empty +#WOODPECKER_AGENT_SECRET= + +# Server-side enforcement policy on the minimum amount of time a client should wait before sending a keepalive ping. +# Default: empty +# Example: WOODPECKER_KEEPALIVE_MIN_TIME=10s +#WOODPECKER_KEEPALIVE_MIN_TIME= + +# Database configuration documentation can be found here: https://woodpecker-ci.org/docs/administration/database +# The database driver name. Possible values are sqlite3, mysql or postgres. +# Default: sqlite3 +WOODPECKER_DATABASE_DRIVER=postgres + +# The database connection string. The default value is the path of the embedded sqlite database file. +# Default: woodpecker.sqlite +# MySQL Example: +# https://github.com/go-sql-driver/mysql#dsn-data-source-name +# WOODPECKER_DATABASE_DATASOURCE=root:password@tcp(1.2.3.4:3306)/woodpecker?parseTime=true +# +# PostgreSQL Example: +# https://www.postgresql.org/docs/current/static/libpq-connect.html#LIBPQ-CONNSTRING +# WOODPECKER_DATABASE_DATASOURCE=postgres://root:password@1.2.3.4:5432/woodpecker?sslmode=disable +WOODPECKER_DATABASE_DATASOURCE=postgres://__DB_USER__:__DB_PWD__@localhost:5432/__DB_NAME__?sslmode=disable + +# Token to secure the Prometheus metrics endpoint. +# Default: empty +#WOODPECKER_PROMETHEUS_AUTH_TOKEN= + +# Context prefix Woodpecker will use to publish status messages to SCM. You probably will only need to change it if you run multiple Woodpecker instances for a single repository. +# Default: ci/woodpecker +#WOODPECKER_STATUS_CONTEXT= + +# The maximum amount of memory a single pipeline container is allowed to swap to disk, configured in bytes. There is no limit if 0. +# Default: 0 +#WOODPECKER_LIMIT_MEM_SWAP= + +# The maximum amount of memory a single pipeline container can use, configured in bytes. There is no limit if 0. +# Default: 0 +#WOODPECKER_LIMIT_MEM= + +# The maximum amount of memory of /dev/shm allowed in bytes. There is no limit if 0. +# Default: 0 +#WOODPECKER_LIMIT_SHM_SIZE= + +# The number of microseconds per CPU period that the container is limited to before throttled. There is no limit if 0. +# Default: 0 +#WOODPECKER_LIMIT_CPU_QUOTA= + +# The relative weight vs. other containers. +# Default: 0 +#WOODPECKER_LIMIT_CPU_SHARES= + +# Comma-separated list to limit the specific CPUs or cores a pipeline container can use. +# Default: empty +# Example: WOODPECKER_LIMIT_CPU_SET=1,2 +#WOODPECKER_LIMIT_CPU_SET= + + +## Forge configuration from yunohost +__CONFIG_FORGE_TYPE__ +__CONFIG_FORGE_URL__ +__CONFIG_FORGE_CLIENT__ +__CONFIG_FORGE_SECRET__ diff --git a/doc/POST_INSTALL.md b/doc/POST_INSTALL.md deleted file mode 100644 index f367b62..0000000 --- a/doc/POST_INSTALL.md +++ /dev/null @@ -1,7 +0,0 @@ -This is a dummy disclaimer to display after the install - -The app url is `__DOMAIN____PATH__` - -The app install dir is `__INSTALL_DIR__` - -The app id is `__ID__` diff --git a/doc/POST_UPGRADE.md b/doc/POST_UPGRADE.md deleted file mode 100644 index a58e2ae..0000000 --- a/doc/POST_UPGRADE.md +++ /dev/null @@ -1 +0,0 @@ -This is a dummy disclaimer to display after upgrades diff --git a/doc/PRE_INSTALL.md b/doc/PRE_INSTALL.md index eb3ab3a..199aba2 100644 --- a/doc/PRE_INSTALL.md +++ b/doc/PRE_INSTALL.md @@ -1 +1,3 @@ -This is a dummy disclaimer to display prior to the install +This app requires a connection to a Git forge configured at installation time. + +Visit for details about retrieving the client ID and secret. diff --git a/doc/PRE_INSTALL_fr.md b/doc/PRE_INSTALL_fr.md index 4a02cd5..a7e31f0 100644 --- a/doc/PRE_INSTALL_fr.md +++ b/doc/PRE_INSTALL_fr.md @@ -1 +1,3 @@ -Ceci est un faux disclaimer à présenter avant l'installation +Cette application nécessite la configuration d'une connection à une forge Git à l'installation. + +Visitez pour savoir comment obtenir l'ID de client et le secret. diff --git a/doc/PRE_UPGRADE.md b/doc/PRE_UPGRADE.md deleted file mode 100644 index 780fc15..0000000 --- a/doc/PRE_UPGRADE.md +++ /dev/null @@ -1 +0,0 @@ -This is a dummy disclaimer to display prior to any upgrade diff --git a/doc/screenshots/example.jpg b/doc/screenshots/example.jpg deleted file mode 100644 index a1efa1a36d593384df59dc13db03fa83b0436d69..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 35451 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 UE-)&$xd9C0IsX9d#{5|Pe`qLcKmY&$ diff --git a/doc/screenshots/woodpecker.png b/doc/screenshots/woodpecker.png new file mode 100644 index 0000000000000000000000000000000000000000..b92f3589f55d79a17069e44ca23b44cf91e6139c GIT binary patch literal 71639 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 e9QGTxvTWV db.sql +ynh_psql_dump_db --database="$db_name" > db.sql #================================================= # END OF SCRIPT diff --git a/scripts/install b/scripts/install index cd1d842..4d68dab 100755 --- a/scripts/install +++ b/scripts/install @@ -9,27 +9,6 @@ source _common.sh source /usr/share/yunohost/helpers -# Install parameters are automatically saved as settings -# -# Settings are automatically loaded as bash variables -# in every app script context, therefore typically these will exist: -# - $domain -# - $path -# - $language -# ... etc -# -# Resources defined in the manifest are provisioned prior to this script -# and corresponding settings are also available, such as: -# - $install_dir -# - $port -# - $db_name -# ... - -# -# $app is the app id (i.e. 'example' for first install, -# or 'example__2', '__3', ... for multi-instance installs) -# - #================================================= # APP "BUILD" (DEPLOYING SOURCES, VENV, COMPILING ETC) #================================================= @@ -37,64 +16,21 @@ source /usr/share/yunohost/helpers #================================================= ynh_script_progression --message="Setting up source files..." --weight=1 -### `ynh_setup_source` is used to install an app from a zip or tar.gz file, -### downloaded from an upstream source, like a git repository. -### `ynh_setup_source` use the file conf/app.src - -# Download, check integrity, uncompress and patch the source from app.src ynh_setup_source --dest_dir="$install_dir" -# $install_dir will automatically be initialized with some decent -# permission by default ... however, you may need to recursively reapply -# ownership to all files such as after the ynh_setup_source step -chown -R $app:www-data "$install_dir" +chown -R "$app:www-data" "$install_dir" +ls -lah "$install_dir" #================================================= # SYSTEM CONFIGURATION #================================================= ynh_script_progression --message="Adding system configurations related to $app..." --weight=1 -### `ynh_add_fpm_config` is used to set up a PHP config. -### You can remove it if your app doesn't use PHP. -### `ynh_add_fpm_config` will use the files conf/php-fpm.conf -### If you're not using these lines: -### - You can remove these files in conf/. -### - Remove the section "BACKUP THE PHP-FPM CONFIGURATION" in the backup script -### - Remove also the section "REMOVE PHP-FPM CONFIGURATION" in the remove script -### - As well as the section "RESTORE THE PHP-FPM CONFIGURATION" in the restore script -### with the reload at the end of the script. -### - And the section "PHP-FPM CONFIGURATION" in the upgrade script - -# Create a dedicated PHP-FPM config using the conf/php-fpm.conf or conf/extra_php-fpm.conf -ynh_add_fpm_config - -# Create a dedicated NGINX config using the conf/nginx.conf template ynh_add_nginx_config -### `ynh_systemd_config` is used to configure a systemd script for an app. -### It can be used for apps that use sysvinit (with adaptation) or systemd. -### Have a look at the app to be sure this app needs a systemd script. -### `ynh_systemd_config` will use the file conf/systemd.service -### If you're not using these lines: -### - You can remove those files in conf/. -### - Remove the section "BACKUP SYSTEMD" in the backup script -### - Remove also the section "STOP AND REMOVE SERVICE" in the remove script -### - As well as the section "RESTORE SYSTEMD" in the restore script -### - And the section "SETUP SYSTEMD" in the upgrade script - -# Create a dedicated systemd config ynh_add_systemd_config -### `yunohost service add` integrates a service in YunoHost. It then gets -### displayed in the admin interface and through the others `yunohost service` commands. -### (N.B.: this line only makes sense if the app adds a service to the system!) -### If you're not using these lines: -### - You can remove these files in conf/. -### - Remove the section "REMOVE SERVICE INTEGRATION IN YUNOHOST" in the remove script -### - As well as the section "INTEGRATE SERVICE IN YUNOHOST" in the restore script -### - And the section "INTEGRATE SERVICE IN YUNOHOST" in the upgrade script - -yunohost service add $app --description="A short description of the app" --log="/var/log/$app/$app.log" +yunohost service add "$app" --description="Woodpecker CI server" --log="/var/log/$app/$app.log" ### Additional options starting with 3.8: ### @@ -124,7 +60,7 @@ yunohost service add $app --description="A short description of the app" --log=" ynh_use_logrotate # Create a dedicated Fail2Ban config -ynh_add_fail2ban_config --logpath="/var/log/nginx/${domain}-error.log" --failregex="Regex to match into the log for a failed login" +# ynh_add_fail2ban_config --logpath="/var/log/nginx/${domain}-error.log" --failregex="Regex to match into the log for a failed login" #================================================= # APP INITIAL CONFIGURATION @@ -133,45 +69,12 @@ ynh_add_fail2ban_config --logpath="/var/log/nginx/${domain}-error.log" --failreg #================================================= ynh_script_progression --message="Adding a configuration file..." --weight=1 -### You can add specific configuration files. -### -### Typically, put your template conf file in ../conf/your_config_file -### The template may contain strings such as __FOO__ or __FOO_BAR__, -### which will automatically be replaced by the values of $foo and $foo_bar -### -### ynh_add_config will also keep track of the config file's checksum, -### which later during upgrade may allow to automatically backup the config file -### if it's found that the file was manually modified -### -### Check the documentation of `ynh_add_config` for more info. +path_no_trailing_slash=${path%/} +_woodpecker_set_forge_config -ynh_add_config --template="some_config_file" --destination="$install_dir/some_config_file" - -# FIXME: this should be handled by the core in the future -# You may need to use chmod 600 instead of 400, -# for example if the app is expected to be able to modify its own config -chmod 400 "$install_dir/some_config_file" -chown $app:$app "$install_dir/some_config_file" - -### For more complex cases where you want to replace stuff using regexes, -### you shoud rely on ynh_replace_string (which is basically a wrapper for sed) -### When doing so, you also need to manually call ynh_store_file_checksum -### -### ynh_replace_string --match_string="match_string" --replace_string="replace_string" --target_file="$install_dir/some_config_file" -### ynh_store_file_checksum --file="$install_dir/some_config_file" - -#================================================= -# SETUP APPLICATION WITH CURL -#================================================= - -### Use these lines only if the app installation needs to be finalized through -### web forms. We generally don't want to ask the final user, -### so we're going to use curl to automatically fill the fields and submit the -### forms. - -# Installation with curl -ynh_script_progression --message="Finalizing installation..." --weight=1 -ynh_local_curl "/INSTALL_PATH" "key1=value1" "key2=value2" "key3=value3" +ynh_add_config --template="woodpecker-server.conf" --destination="$install_dir/woodpecker-server.conf" +chmod 400 "$install_dir/woodpecker-server.conf" +chown "$app:$app" "$install_dir/woodpecker-server.conf" #================================================= # GENERIC FINALIZATION @@ -189,7 +92,7 @@ ynh_script_progression --message="Starting a systemd service..." --weight=1 ### - And the section "STOP SYSTEMD SERVICE" and "START SYSTEMD SERVICE" in the change_url script # Start a systemd service -ynh_systemd_action --service_name=$app --action="start" --log_path="/var/log/$app/$app.log" +ynh_systemd_action --service_name="$app" --action="start" --log_path="/var/log/$app/$app.log" #================================================= # END OF SCRIPT diff --git a/scripts/remove b/scripts/remove index 097c3f4..05b7974 100755 --- a/scripts/remove +++ b/scripts/remove @@ -9,52 +9,29 @@ source _common.sh source /usr/share/yunohost/helpers -# Settings are automatically loaded as bash variables -# in every app script context, therefore typically these will exist: -# - $domain -# - $path -# - $language -# - $install_dir -# - $port -# ... - -# For remove operations : -# - the core will deprovision every resource defined in the manifest **after** this script is ran -# this includes removing the install directory, and data directory (if --purge was used) - #================================================= # REMOVE SYSTEM CONFIGURATIONS #================================================= -# REMOVE SYSTEMD SERVICE +# REMOVE SYSTEMD SERVICE #================================================= ynh_script_progression --message="Removing system configurations related to $app..." --weight=1 # This should be a symetric version of what happens in the install script # Remove the service from the list of services known by YunoHost (added from `yunohost service add`) -if ynh_exec_warn_less yunohost service status $app >/dev/null +if ynh_exec_warn_less yunohost service status "$app" >/dev/null then ynh_script_progression --message="Removing $app service integration..." --weight=1 - yunohost service remove $app + yunohost service remove "$app" fi ynh_remove_systemd_config ynh_remove_nginx_config -ynh_remove_fpm_config - ynh_remove_logrotate -ynh_remove_fail2ban_config - -# Remove other various files specific to the app... such as : - -ynh_secure_remove --file="/etc/cron.d/$app" - -ynh_secure_remove --file="/etc/$app" - -ynh_secure_remove --file="/var/log/$app" +# ynh_remove_fail2ban_config #================================================= # END OF SCRIPT diff --git a/scripts/restore b/scripts/restore index e60cb7a..b675aec 100755 --- a/scripts/restore +++ b/scripts/restore @@ -17,27 +17,14 @@ ynh_script_progression --message="Restoring the app main directory..." --weight= ynh_restore_file --origin_path="$install_dir" -# $install_dir will automatically be initialized with some decent -# permissions by default ... however, you may need to recursively reapply -# ownership to all files such as after the ynh_setup_source step -chown -R $app:www-data "$install_dir" - -#================================================= -# RESTORE THE DATA DIRECTORY -#================================================= -ynh_script_progression --message="Restoring the data directory..." --weight=1 - -ynh_restore_file --origin_path="$data_dir" --not_mandatory - -# (Same as for install dir) -chown -R $app:www-data "$data_dir" +chown -R "$app:www-data" "$install_dir" #================================================= # RESTORE THE MYSQL DATABASE #================================================= ynh_script_progression --message="Restoring the MySQL database..." --weight=1 -ynh_mysql_connect_as --user=$db_user --password=$db_pwd --database=$db_name < ./db.sql +ynh_psql_connect_as --user="$db_user" --password="$db_pwd" --database="$db_name" < ./db.sql #================================================= # RESTORE SYSTEM CONFIGURATIONS @@ -46,27 +33,18 @@ ynh_mysql_connect_as --user=$db_user --password=$db_pwd --database=$db_name < ./ #================================================= ynh_script_progression --message="Restoring system configurations related to $app..." --weight=1 -# This should be a symetric version of what happens in the install script - -ynh_restore_file --origin_path="/etc/php/$phpversion/fpm/pool.d/$app.conf" - ynh_restore_file --origin_path="/etc/nginx/conf.d/$domain.d/$app.conf" ynh_restore_file --origin_path="/etc/systemd/system/$app.service" -systemctl enable $app.service --quiet +systemctl enable "$app.service" --quiet -yunohost service add $app --description="A short description of the app" --log="/var/log/$app/$app.log" +yunohost service add "$app" --description="Woodpecker CI server" --log="/var/log/$app/$app.log" ynh_restore_file --origin_path="/etc/logrotate.d/$app" -ynh_restore_file --origin_path="/etc/fail2ban/jail.d/$app.conf" -ynh_restore_file --origin_path="/etc/fail2ban/filter.d/$app.conf" -ynh_systemd_action --action=restart --service_name=fail2ban - -# Other various files... - -ynh_restore_file --origin_path="/etc/cron.d/$app" -ynh_restore_file --origin_path="/etc/$app/" +# ynh_restore_file --origin_path="/etc/fail2ban/jail.d/$app.conf" +# ynh_restore_file --origin_path="/etc/fail2ban/filter.d/$app.conf" +# ynh_systemd_action --action=restart --service_name=fail2ban #================================================= # GENERIC FINALIZATION @@ -76,8 +54,7 @@ ynh_restore_file --origin_path="/etc/$app/" ynh_script_progression --message="Reloading NGINX web server and $app's service..." --weight=1 # Typically you only have either $app or php-fpm but not both at the same time... -ynh_systemd_action --service_name=$app --action="start" --log_path="/var/log/$app/$app.log" -ynh_systemd_action --service_name=php$phpversion-fpm --action=reload +ynh_systemd_action --service_name="$app" --action="start" --log_path="/var/log/$app/$app.log" ynh_systemd_action --service_name=nginx --action=reload diff --git a/scripts/upgrade b/scripts/upgrade index 55e1829..fa0b748 100755 --- a/scripts/upgrade +++ b/scripts/upgrade @@ -9,25 +9,6 @@ source _common.sh source /usr/share/yunohost/helpers -# Settings are automatically loaded as bash variables -# in every app script context, therefore typically these will exist: -# - $domain -# - $path -# - $language -# - $install_dir -# - $port -# ... - -# In the context of upgrade, -# - resources are automatically provisioned / updated / deleted (depending on existing resources) -# - a safety backup is automatically created by the core and will be restored if the upgrade fails - -### This helper will compare the version of the currently installed app and the version of the upstream package. -### $upgrade_type can have 2 different values -### - UPGRADE_APP if the upstream app version has changed -### - UPGRADE_PACKAGE if only the YunoHost package has changed -### ynh_check_app_version_changed will stop the upgrade if the app is up to date. -### UPGRADE_APP should be used to upgrade the core app only if there's an upgrade to do. upgrade_type=$(ynh_check_app_version_changed) #================================================= @@ -60,7 +41,7 @@ upgrade_type=$(ynh_check_app_version_changed) #================================================= ynh_script_progression --message="Stopping a systemd service..." --weight=1 -ynh_systemd_action --service_name=$app --action="stop" --log_path="/var/log/$app/$app.log" +ynh_systemd_action --service_name="$app" --action="stop" --log_path="/var/log/$app/$app.log" #================================================= # "REBUILD" THE APP (DEPLOY NEW SOURCES, RERUN NPM BUILD...) @@ -76,29 +57,22 @@ then ynh_setup_source --dest_dir="$install_dir" fi -# $install_dir will automatically be initialized with some decent -# permissions by default ... however, you may need to recursively reapply -# ownership to all files such as after the ynh_setup_source step -chown -R $app:www-data "$install_dir" +chown -R "$app:www-data" "$install_dir" #================================================= # REAPPLY SYSTEM CONFIGURATIONS #================================================= ynh_script_progression --message="Upgrading system configurations related to $app..." --weight=1 -# This should be a literal copypaste of what happened in the install's "System configuration" section - -ynh_add_fpm_config - ynh_add_nginx_config ynh_add_systemd_config -yunohost service add $app --description="A short description of the app" --log="/var/log/$app/$app.log" +yunohost service add "$app" --description="Woodpecker CI server" --log="/var/log/$app/$app.log" ynh_use_logrotate --non-append -ynh_add_fail2ban_config --logpath="/var/log/nginx/${domain}-error.log" --failregex="Regex to match into the log for a failed login" +# ynh_add_fail2ban_config --logpath="/var/log/nginx/${domain}-error.log" --failregex="Regex to match into the log for a failed login" #================================================= # RECONFIGURE THE APP (UPDATE CONF, APPLY MIGRATIONS...) @@ -107,32 +81,19 @@ ynh_add_fail2ban_config --logpath="/var/log/nginx/${domain}-error.log" --failreg #================================================= ynh_script_progression --message="Updating a configuration file..." --weight=1 -### Same as during install -### -### The file will automatically be backed-up if it's found to be manually modified (because -### ynh_add_config keeps track of the file's checksum) +path_no_trailing_slash=${path%/} +_woodpecker_set_forge_config -ynh_add_config --template="some_config_file" --destination="$install_dir/some_config_file" - -# FIXME: this should be handled by the core in the future -# You may need to use chmod 600 instead of 400, -# for example if the app is expected to be able to modify its own config -chmod 400 "$install_dir/some_config_file" -chown $app:$app "$install_dir/some_config_file" - -### For more complex cases where you want to replace stuff using regexes, -### you shoud rely on ynh_replace_string (which is basically a wrapper for sed) -### When doing so, you also need to manually call ynh_store_file_checksum -### -### ynh_replace_string --match_string="match_string" --replace_string="replace_string" --target_file="$install_dir/some_config_file" -### ynh_store_file_checksum --file="$install_dir/some_config_file" +ynh_add_config --template="woodpecker-server.conf" --destination="$install_dir/woodpecker-server.conf" +chmod 400 "$install_dir/woodpecker-server.conf" +chown "$app:$app" "$install_dir/woodpecker-server.conf" #================================================= # START SYSTEMD SERVICE #================================================= ynh_script_progression --message="Starting a systemd service..." --weight=1 -ynh_systemd_action --service_name=$app --action="start" --log_path="/var/log/$app/$app.log" +ynh_systemd_action --service_name="$app" --action="start" --log_path="/var/log/$app/$app.log" #================================================= # END OF SCRIPT diff --git a/tests.toml b/tests.toml new file mode 100644 index 0000000..9a8d950 --- /dev/null +++ b/tests.toml @@ -0,0 +1,29 @@ +#:schema https://raw.githubusercontent.com/YunoHost/apps/master/schemas/tests.v1.schema.json + +test_format = 1.0 + +[default] + + # exclude = ["install.private", "install.multi"] + # The test IDs to be used in only/exclude statements are: + # * install.root + # * install.subdir + # * install.nourl + # * install.multi + # * backup_restore + # * upgrade + # * upgrade.someCommitId + # * change_url + # NB: you should NOT need this except if you really have a good reason... + + # For special usecases, sometimes you need to setup other things on the machine + # prior to installing the app (such as installing another app) + # (Remove this key entirely if not needed) + # preinstall = """ + # sudo yunohost app install foobar + # sudo yunohost user list + # """ + args.forge_type = "github" + args.forge_url = "https://github.com" + args.forge_client = "dammy client" + args.forge_secret = "dummy secret" diff --git a/tests.toml.example b/tests.toml.example deleted file mode 100644 index 26bb7e4..0000000 --- a/tests.toml.example +++ /dev/null @@ -1,67 +0,0 @@ -#:schema https://raw.githubusercontent.com/YunoHost/apps/master/schemas/tests.v1.schema.json - -test_format = 1.0 - -[default] - - # ------------ - # Tests to run - # ------------ - - # NB: the tests to run are automatically deduced by the CI script according to the - # content of the app's manifest. The declarations below allow to customize which - # tests are ran, possibly add special test suite to test special args, or - # declare which commits to test upgrade from. - # - # You can also decide (though this is discouraged!) to ban/ignore some tests, - - exclude = ["install.private", "install.multi"] - # The test IDs to be used in only/exclude statements are: - # * install.root - # * install.subdir - # * install.nourl - # * install.multi - # * backup_restore - # * upgrade - # * upgrade.someCommitId - # * change_url - # NB: you should NOT need this except if you really have a good reason... - - # For special usecases, sometimes you need to setup other things on the machine - # prior to installing the app (such as installing another app) - # (Remove this key entirely if not needed) - preinstall = """ - sudo yunohost app install foobar - sudo yunohost user list - """ - - # ------------------------------- - # Default args to use for install - # ------------------------------- - - # By default, the CI will automagically fill the 'standard' args - # such as domain, path, admin, is_public and password with relevant values - # and also install args with a "default" provided in the manifest.. - # It should only make sense to declare custom args here for args with no default values - - args.language = "fr_FR" - args.multisite = 0 - # NB: you should NOT need those lines unless for custom questions with no obvious/default value - - # ------------------------------- - # Commits to test upgrade from - # ------------------------------- - - test_upgrade_from.00a1a6e7.name = "Upgrade from 5.4" - test_upgrade_from.00a1a6e7.args.foo = "bar" - - -# This is an additional test suite -[some_additional_testsuite] - - # On additional tests suites, you can decide to run only specific tests - - only = ["install.subdir"] - - args.language = "en_GB" - args.multisite = 1