parent
839d2f87f5
commit
706038bf09
@ -0,0 +1,3 @@
|
||||
[submodule "Git-Auto-Deploy"]
|
||||
path = deploy/Git-Auto-Deploy
|
||||
url = https://github.com/olipo186/Git-Auto-Deploy.git
|
@ -0,0 +1,86 @@
|
||||
# Byte-compiled / optimized / DLL files
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
*$py.class
|
||||
|
||||
# C extensions
|
||||
*.so
|
||||
|
||||
# Distribution / packaging
|
||||
.Python
|
||||
env/
|
||||
build/
|
||||
develop-eggs/
|
||||
dist/
|
||||
downloads/
|
||||
eggs/
|
||||
.eggs/
|
||||
lib/
|
||||
lib64/
|
||||
parts/
|
||||
sdist/
|
||||
var/
|
||||
*.egg-info/
|
||||
.installed.cfg
|
||||
*.egg
|
||||
|
||||
# PyInstaller
|
||||
# Usually these files are written by a python script from a template
|
||||
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||
*.manifest
|
||||
*.spec
|
||||
|
||||
# Installer logs
|
||||
pip-log.txt
|
||||
pip-delete-this-directory.txt
|
||||
|
||||
# Unit test / coverage reports
|
||||
htmlcov/
|
||||
.tox/
|
||||
.coverage
|
||||
.coverage.*
|
||||
.cache
|
||||
nosetests.xml
|
||||
coverage.xml
|
||||
*,cover
|
||||
|
||||
# Translations
|
||||
*.mo
|
||||
*.pot
|
||||
|
||||
# Django stuff:
|
||||
*.log
|
||||
|
||||
# Sphinx documentation
|
||||
docs/_build/
|
||||
|
||||
# PyBuilder
|
||||
target/
|
||||
|
||||
GitAutoDeploy.conf.json
|
||||
config.json
|
||||
*.tc.json
|
||||
|
||||
.idea
|
||||
.DS_Store
|
||||
._.DS_Store
|
||||
.fuse*
|
||||
|
||||
# Ignore
|
||||
deb_dist
|
||||
*.tar.gz
|
||||
MANIFEST
|
||||
|
||||
# dependencies
|
||||
webui/node_modules
|
||||
|
||||
# testing
|
||||
webui/coverage
|
||||
|
||||
# production
|
||||
webui/build
|
||||
|
||||
# misc
|
||||
.DS_Store
|
||||
.env
|
||||
npm-debug.log
|
@ -0,0 +1,14 @@
|
||||
language: python
|
||||
python:
|
||||
- "2.6"
|
||||
# - "2.7"
|
||||
# - "3.2"
|
||||
# - "3.3"
|
||||
# - "3.4"
|
||||
- "3.5"
|
||||
# - "3.5-dev" # 3.5 development branch
|
||||
# - "nightly" # currently points to 3.6-dev
|
||||
# command to install dependencies
|
||||
install: "pip install -r requirements.txt"
|
||||
# command to run tests
|
||||
script: python test/test_parsers.py
|
@ -0,0 +1,9 @@
|
||||
FROM google/python-runtime
|
||||
|
||||
RUN apt-get update && \
|
||||
apt-get -y install openssh-client
|
||||
|
||||
RUN mkdir $HOME/.ssh && chmod 600 $HOME/.ssh
|
||||
COPY deploy_rsa /root/.ssh/id_rsa
|
||||
|
||||
ENTRYPOINT ["/env/bin/python", "-u", "GitAutoDeploy.py", "--ssh-keyscan"]
|
@ -0,0 +1,8 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
if __name__ == '__main__':
|
||||
import sys
|
||||
import os
|
||||
import gitautodeploy
|
||||
sys.stderr.write("\033[1;33m[WARNING]\033[0;33m GitAutoDeploy.py is deprecated. Please use \033[1;33m'python gitautodeploy%s'\033[0;33m instead.\033[0m\n" % (' ' + ' '.join(sys.argv[1:])).rstrip())
|
||||
gitautodeploy.main()
|
Binary file not shown.
@ -0,0 +1,102 @@
|
||||
.PHONY: all detect install initsystem
|
||||
|
||||
prefix = /opt/Git-Auto-Deploy/
|
||||
|
||||
#init_version := $(shell /sbin/init --version 2>&1)
|
||||
#test_upstart := $(shell printf $(init_version) | grep -q upstart || grep -q upstart /proc/net/unix ; echo $$?)
|
||||
#test_systemd := $(shell printf $(init_version) | grep -q systemd || grep -q systemd /proc/1/comm || grep -q systemd /proc/net/unix ; echo $$?)
|
||||
|
||||
PYTHON ?= python2
|
||||
|
||||
# Debian distos to create packages for
|
||||
DISTROS= \
|
||||
bionic \
|
||||
artful \
|
||||
xenial \
|
||||
trusty \
|
||||
precise
|
||||
|
||||
# Package name and version
|
||||
PACKAGE_NAME=$(shell python setup.py --name)
|
||||
PACKAGE_VERSION=$(shell python setup.py --version)
|
||||
|
||||
define version =
|
||||
echo "hello"
|
||||
exit 1
|
||||
endef
|
||||
|
||||
all:
|
||||
|
||||
clean: clean-pypi clean-deb
|
||||
rm -rf *.tar.gz
|
||||
|
||||
clean-pypi:
|
||||
rm -rf *.egg-info
|
||||
rm -rf dist/pypi
|
||||
if [ -d "dist" ]; then rmdir --ignore-fail-on-non-empty dist; fi
|
||||
|
||||
pypi:
|
||||
$(PYTHON) setup.py sdist --dist-dir dist/pypi
|
||||
|
||||
upload-pypi:
|
||||
$(PYTHON) setup.py sdist --dist-dir dist/pypi register upload -r pypi
|
||||
|
||||
clean-deb:
|
||||
rm -rf dist/deb
|
||||
rm -f dist/*.tar.gz
|
||||
if [ -d "dist" ]; then rmdir --ignore-fail-on-non-empty dist; fi
|
||||
|
||||
# Usage: make deb-source [DIST=<debian dist>]
|
||||
deb-source: clean-deb
|
||||
@- $(foreach DIST,$(DISTROS), \
|
||||
echo "Creating deb source package for dist $(DIST)" ; \
|
||||
echo "Make a debian source package using stdeb" ; \
|
||||
python setup.py --command-packages=stdeb.command sdist_dsc -x platforms/debian/stdeb.cfg --dist-dir dist/deb --debian-version $(DIST) --suite $(DIST) --upstream-version-suffix "~$(DIST)" ; \
|
||||
echo "Copy debian package config files" ; \
|
||||
cp -vr platforms/debian/stdeb/* dist/deb/$(PACKAGE_NAME)-$(PACKAGE_VERSION)~$(DIST)/debian/ ; \
|
||||
)
|
||||
|
||||
deb: clean-deb deb-source
|
||||
@- $(foreach DIST,$(DISTROS), \
|
||||
echo "Creating unsigned deb package for dist $(DIST)" ; \
|
||||
echo "Build .deb package (without signing)" ; \
|
||||
cd dist/deb/$(PACKAGE_NAME)-$(PACKAGE_VERSION)~$(DIST) ; \
|
||||
dpkg-buildpackage -rfakeroot -uc -us ; \
|
||||
cd ../../../ ; \
|
||||
)
|
||||
|
||||
signed-deb: clean-deb deb-source
|
||||
@- $(foreach DIST,$(DISTROS), \
|
||||
echo "Creating signed deb package for dist $(DIST)" ; \
|
||||
echo "Build .deb package (signed)" ; \
|
||||
cd dist/deb/$(PACKAGE_NAME)-$(PACKAGE_VERSION)~$(DIST) ; \
|
||||
debuild -S -sa ; \
|
||||
cd ../../../ ; \
|
||||
)
|
||||
|
||||
upload-deb: clean-deb signed-deb
|
||||
@- $(foreach DIST,$(DISTROS), \
|
||||
echo "Upload signed debian package to ppa for dist $(DIST)" ; \
|
||||
dput ppa:olipo186/$(PACKAGE_NAME) dist/deb/$(PACKAGE_NAME)_$(PACKAGE_VERSION)~$(DIST)-$(DIST)_source.changes ; \
|
||||
)
|
||||
|
||||
|
||||
#initsystem:
|
||||
#ifeq ($(test_upstart),0)
|
||||
# @echo "Upstart detected!"
|
||||
#else ifeq ($(test_systemd),0)
|
||||
# @echo "Systemd detected!"
|
||||
#else
|
||||
# @echo "InitV supposed"
|
||||
#endif
|
||||
# @echo "Init script not installed - not yet implemented"
|
||||
|
||||
#install: clean all
|
||||
# @echo "Installing deploy script in $(prefix) ..."
|
||||
# @echo "Installing deploy script in $(init_version) ..."
|
||||
# @sudo mkdir $(prefix) &> /dev/null || true
|
||||
# @sudo cp config.json.sample $(prefix)config.json
|
||||
# @sudo cp -r gitautodeploy $(prefix)/
|
||||
#
|
||||
# @echo "Installing run-on-startup scripts according to your init system ..."
|
||||
# @make initsystem
|
@ -0,0 +1,128 @@
|
||||
[![Build Status](https://travis-ci.org/olipo186/Git-Auto-Deploy.svg?branch=master)](https://travis-ci.org/olipo186/Git-Auto-Deploy)
|
||||
# What is it?
|
||||
|
||||
Git-Auto-Deploy consists of a small HTTP server that listens for Webhook requests sent from GitHub, GitLab or Bitbucket servers. This application allows you to continuously and automatically deploy your projects each time you push new commits to your repository.</p>
|
||||
|
||||
![workflow](https://cloud.githubusercontent.com/assets/1056476/9344294/d3bc32a4-4607-11e5-9a44-5cd9b22e61d9.png)
|
||||
|
||||
# How does it work?
|
||||
|
||||
When commits are pushed to your Git repository, the Git server will notify ```Git-Auto-Deploy``` by sending an HTTP POST request with a JSON body to a pre-configured URL (your-host:8001). The JSON body contains detailed information about the repository and what event that triggered the request. ```Git-Auto-Deploy``` parses and validates the request, and if all goes well it issues a ```git pull```.
|
||||
|
||||
Additionally, ```Git-Auto-Deploy``` can be configured to execute a shell command upon each successful ```git pull```, which can be used to trigger custom build actions or test scripts.</p>
|
||||
|
||||
# Getting started
|
||||
|
||||
You can install ```Git-Auto-Deploy``` in multiple ways. Below are instructions for the most common methods.
|
||||
|
||||
## Install from PPA (recommended for Ubuntu systems)
|
||||
|
||||
[Using Debian? Have a look at this answer for instructions.](https://github.com/olipo186/Git-Auto-Deploy/issues/153)
|
||||
|
||||
Add our PPA repository.
|
||||
|
||||
sudo apt-get install software-properties-common
|
||||
sudo add-apt-repository ppa:olipo186/git-auto-deploy
|
||||
sudo apt-get update
|
||||
|
||||
Install ```Git-Auto-Deploy``` using apt.
|
||||
|
||||
sudo apt-get install git-auto-deploy
|
||||
|
||||
Modify the configuration file to match your project setup. [Read more about the configuration options](./docs/Configuration.md).
|
||||
|
||||
nano /etc/git-auto-deploy.conf.json
|
||||
|
||||
Optional: Copy any private SSH key you wish to use to the home directory of GAD.
|
||||
|
||||
sudo cp /path/to/id_rsa /etc/git-auto-deploy/.ssh/
|
||||
sudo chown -R git-auto-deploy:git-auto-deploy /etc/git-auto-deploy
|
||||
|
||||
Start ```Git-Auto-Deploy``` and check it's status.
|
||||
|
||||
service git-auto-deploy start
|
||||
service git-auto-deploy status
|
||||
|
||||
## Install from repository (recommended for other systems)
|
||||
|
||||
When installing ```Git-Auto-Deploy``` from the repository, you'll need to make sure that Python (tested on version 2.7) and Git (tested on version 2.5.0) is installed on your system.
|
||||
|
||||
Clone the repository.
|
||||
|
||||
git clone https://github.com/olipo186/Git-Auto-Deploy.git
|
||||
|
||||
Install the dependencies with [pip](http://www.pip-installer.org/en/latest/), a package manager for Python, by running the following command.
|
||||
|
||||
sudo pip install -r requirements.txt
|
||||
|
||||
If you don't have pip installed, try installing it by running this from the command
|
||||
line:
|
||||
|
||||
curl https://bootstrap.pypa.io/get-pip.py | python
|
||||
|
||||
Copy of the sample config and modify it. [Read more about the configuration options](./docs/Configuration.md). Make sure that ```pidfilepath``` is writable for the user running the script, as well as all paths configured for your repositories.
|
||||
|
||||
cd Git-Auto-Deploy
|
||||
cp config.json.sample config.json
|
||||
|
||||
Start ```Git-Auto-Deploy``` manually using;
|
||||
|
||||
python -m gitautodeploy --config config.json
|
||||
|
||||
To start ```Git-Auto-Deploy``` automatically on boot, open crontab in edit mode using ```crontab -e``` and add the entry below.
|
||||
|
||||
@reboot /usr/bin/python -m /path/to/Git-Auto-Deploy/gitautodeploy --daemon-mode --quiet --config /path/to/git-auto-deploy.conf.json
|
||||
|
||||
You can also configure ```Git-Auto-Deploy``` to start on boot using an init.d-script (for Debian and Sys-V like init systems) or a service for systemd.[Read more about starting Git-Auto-Deploy automatically using init.d or systemd](./docs/Start%20automatically%20on%20boot.md).
|
||||
|
||||
## Install and run GAD under Windows
|
||||
GAD runs under Windows but requires some requisites.
|
||||
|
||||
1. Install Python 2.7 using the [Windows installer](https://www.python.org/downloads/).
|
||||
2. Verify that Python is added to your [system PATH](https://technet.microsoft.com/en-us/library/cc772047(v=ws.11).aspx). Make sure ``C:\Python27`` and ``C:\Python27\Scripts`` is part of the PATH system environment variable.
|
||||
3. Install pip using the [``get-pip.py`` script](https://pip.pypa.io/en/latest/installing/)
|
||||
4. Install Git using the [official Git build for Windows](https://git-scm.com/download/win)
|
||||
5. Verify that Git is added to your [system PATH](https://technet.microsoft.com/en-us/library/cc772047(v=ws.11).aspx). Make sure that ```C:\Program Files\Git\cmd``` is added (should have been added automatically by the installer) as well as ```C:\Program Files\Git\bin``` (*not* added by default).
|
||||
6. Continue with the above instructions for [installing GAD from the repository](#install-from-repository-recommended-for-other-systems)
|
||||
|
||||
## Alternative installation methods
|
||||
|
||||
* [Install as a python module (experimental)](./docs/Install%20as%20a%20python%20module.md)
|
||||
* [Install as a debian package (experimental)](./docs/Install%20as%20a%20debian%20package.md)
|
||||
* [Start automatically on boot (init.d and systemd)](./docs/Start%20automatically%20on%20boot.md)
|
||||
|
||||
## Command line options
|
||||
|
||||
Below is a summarized list of the most common command line options. For a full list of available command line options, invoke the application with the argument ```--help``` or read the documentation article about [all available command line options, environment variables and config attributes](./docs/Configuration.md).
|
||||
|
||||
Command line option | Environment variable | Config attribute | Description
|
||||
---------------------- | -------------------- | ---------------- | --------------------------
|
||||
--daemon-mode (-d) | GAD_DAEMON_MODE | | Run in background (daemon mode)
|
||||
--quiet (-q) | GAD_QUIET | | Supress console output
|
||||
--config (-c) <path> | GAD_CONFIG | | Custom configuration file
|
||||
--pid-file <path> | GAD_PID_FILE | pidfilepath | Specify a custom pid file
|
||||
--log-file <path> | GAD_LOG_FILE | logfilepath | Specify a log file
|
||||
--host <host> | GAD_HOST | host | Address to bind to
|
||||
--port <port> | GAD_PORT | port | Port to bind to
|
||||
|
||||
## Getting webhooks from git
|
||||
To make your git provider send notifications to ```Git-Auto-Deploy``` you will need to provide the hostname and port for your ```Git-Auto-Deploy``` instance. Instructions for the most common git providers is listed below.
|
||||
|
||||
**GitHub**
|
||||
1. Go to your repository -> Settings -> Webhooks and Services -> Add webhook</li>
|
||||
2. In "Payload URL", enter your hostname and port (your-host:8001)
|
||||
3. Hit "Add webhook"
|
||||
|
||||
**GitLab**
|
||||
1. Go to your repository -> Settings -> Web hooks
|
||||
2. In "URL", enter your hostname and port (your-host:8001)
|
||||
3. Hit "Add Web Hook"
|
||||
|
||||
**Bitbucket**
|
||||
1. Go to your repository -> Settings -> Webhooks -> Add webhook
|
||||
2. In "URL", enter your hostname and port (your-host:8001)
|
||||
3. Hit "Save"
|
||||
|
||||
# More documentation
|
||||
|
||||
[Have a look in the *docs* directory](./docs), where you'll find more detailed documentation on configurations, alternative installation methods, and example workflows.
|
@ -0,0 +1,70 @@
|
||||
{
|
||||
// HTTP server options
|
||||
//"http-enabled": true,
|
||||
//"http-host": "0.0.0.0",
|
||||
//"http-port": 8001,
|
||||
|
||||
// HTTPS server options
|
||||
//"https-enabled": false,
|
||||
//"https-host": "0.0.0.0",
|
||||
//"https-port": 8002,
|
||||
|
||||
// Web socket server options (used by web UI for real time updates)
|
||||
//"wss-enabled": false,
|
||||
//"wss-host": "0.0.0.0",
|
||||
//"wss-port": 8003,
|
||||
|
||||
// Web user interface options
|
||||
//"web-ui-enabled": false,
|
||||
//"web-ui-username": null,
|
||||
//"web-ui-password": null,
|
||||
//"web-ui-whitelist": ["127.0.0.1"],
|
||||
|
||||
// TLS/SSL cert (necessary for HTTPS and web socket server to work)
|
||||
//"ssl-key": null, // If specified, holds the private key
|
||||
//"ssl-cert": "cert.pem", // Holds the public key or both the private and public keys
|
||||
|
||||
// File to store a copy of the console output
|
||||
"log-file": "~/gitautodeploy.log",
|
||||
|
||||
// File to store the process id (pid)
|
||||
"pid-file": "~/.gitautodeploy.pid",
|
||||
|
||||
// Record all log levels by default
|
||||
"log-level": "INFO",
|
||||
|
||||
// Deploy commands that should be executed for all projects
|
||||
//"global_deploy": [
|
||||
// "echo Deploy started!",
|
||||
// "echo Deploy completed!"
|
||||
//],
|
||||
|
||||
"repositories": [
|
||||
{
|
||||
"url": "https://github.com/olipo186/Git-Auto-Deploy.git",
|
||||
"branch": "master",
|
||||
"remote": "origin",
|
||||
"path": "~/repositories/Git-Auto-Deploy",
|
||||
"deploy": "echo deploying"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/github/gitignore",
|
||||
"path": "~/repositories/gitignore"
|
||||
},
|
||||
{
|
||||
"url": "git@gitlab.com:gitlab-org/gitlab-ce.git",
|
||||
"path": "~/repositories/gitignore"
|
||||
},
|
||||
{
|
||||
"url": "https://api.github.com/repos/olipo186/Git-Auto-Deploy",
|
||||
"deploy": "echo deploying after pull request",
|
||||
"filters": [
|
||||
{
|
||||
"type": "pull-request-filter",
|
||||
"action": "closed",
|
||||
"ref": "testing-branch"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
@ -0,0 +1,343 @@
|
||||
# Command line options and environment variables
|
||||
|
||||
```Git-Auto-Deploy``` supports a number of configurable options. Some of them are available using command line options, where others are only configurable from the config file. Below is a list of the options made available from the command line. Every command line option has also a corresponding environment variable. In the cases where a corresponding config file attribute is available, that attribute name is listed.
|
||||
|
||||
There is also support for supplying configuration options for up to one repository using environmetn variables. Variable names and descriptios are available in the section (Repository configuration using environment variables)[#eepository-configuration-using-environment-variables].
|
||||
|
||||
The list of available command line options can also be seen by invoke the application with the argument ```--help```.
|
||||
|
||||
Command line option | Environment variable | Config attribute | Description
|
||||
---------------------- | -------------------- | ---------------- | --------------------------
|
||||
--daemon-mode (-d) | GAD_DAEMON_MODE | | Run in background (daemon mode)
|
||||
--quiet (-q) | GAD_QUIET | | Supress console output
|
||||
--config (-c) <path> | GAD_CONFIG | | Custom configuration file
|
||||
--pid-file <path> | GAD_PID_FILE | pidfilepath | Specify a custom pid file
|
||||
--log-file <path> | GAD_LOG_FILE | logfilepath | Specify a log file
|
||||
--host <host> | GAD_HOST | host | Address to bind to
|
||||
--port <port> | GAD_PORT | port | Port to bind to
|
||||
--ssh-keyscan | GAD_SSH_KEYSCAN | | Scan repository hosts for ssh keys and add them to $HOME/.ssh/known_hosts
|
||||
|
||||
# Configuration file options
|
||||
The configuration file is formatted according to a `JSON` inspired format, with the additional feature of supporting inline comments. The possible root elements are
|
||||
as follow:
|
||||
|
||||
- **pidfilepath**: The path where `pid` files are kept.
|
||||
- **logfilepath**: To enable logging, set this to a valid file path.
|
||||
- **log-level**: Sets the threshold for the log output. Default value is NOTSET (all details). Recommended value is INFO (less details).
|
||||
- **host**: What IP address to listen on.
|
||||
- **port**: The port for the web server to listen on.
|
||||
- **global_deploy**: An array of two specific commands or path to scripts
|
||||
to be executed for all repositories defined:
|
||||
- `[0]` = The pre-deploy script.
|
||||
- `[1]` = The post-deploy script.
|
||||
- **repositories**: An array of repository configurations.
|
||||
|
||||
## Repositories
|
||||
Repository configurations are comprised of the following elements:
|
||||
|
||||
- **url**: The URL to the repository.
|
||||
- **match-url**: An alternative URL used when matching incoming webhook requests (see https://github.com/olipo186/Git-Auto-Deploy/pull/148)
|
||||
- **branch**: The branch which will be checked out.
|
||||
- **remote**: The name of the remote to use.
|
||||
- **path**: Path to clone the repository to. If omitted, the repository won't
|
||||
be cloned, only the deploy scripts will be executed.
|
||||
- **deploy**: A command to be executed. If `path` is set, the command is
|
||||
executed after a successfull `pull`.
|
||||
- **payload-filter**: A list of inclusive filters/rules that is applied to the request body of incoming web hook requests and determines whether the deploy command should be executed or not. See section *Filters* for more details.
|
||||
- **header-filter**: A set of inclusive filters/rules that is applied to the request header of incoming web hook requests and determines whether the deploy command should be executed or not. See section *Filters* for more details.
|
||||
- **secret-token**: The secret token set for your webhook (currently only implemented for [GitHub](https://developer.github.com/webhooks/securing/) and GitLab)
|
||||
- **prepull**: A command to execute immediately before the `git pull`. This command could do something required for the ``git pull`` to succeed such as changing file permissions.
|
||||
- **postpull**: A command to execute immediately after the `git pull`. After the **prepull** command is executed, **postpull** can clean up any changes made.
|
||||
|
||||
## Filters
|
||||
*(Currently only supported for GitHub and GitLab)*
|
||||
|
||||
With filters, it is possible to trigger the deploy only if a set of specific criterias are met. The filter can be applied to the web hook request header (if specified using the *header-filter* option) or to the request body (*payload-filter*).
|
||||
|
||||
### Allow web hooks with specific header values only (header-filter)
|
||||
|
||||
Some Git providers will add custom HTTP headers in their web hook requests when sending them to GAD. Using a *header-filter*, you can configure GAD to only process web hooks that has a specific HTTP header specified.
|
||||
|
||||
For example, if you'd like to only process requests that has the *X-Event-Key* header set to the value *pullrequest:fulfilled*, you could use the following config;
|
||||
|
||||
```json
|
||||
{
|
||||
...
|
||||
"repositories": [
|
||||
{
|
||||
...
|
||||
"header-filter": {
|
||||
"X-Event-Key": "pullrequest:fulfilled"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
If a header name is specified but with the value set to true, any request that has the header specified will pass without regard to the header value.
|
||||
|
||||
```json
|
||||
{
|
||||
...
|
||||
"repositories": [
|
||||
{
|
||||
...
|
||||
"header-filter": {
|
||||
"X-Event-Key": true
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Allow web hooks with specific payload only (payload-filter)
|
||||
|
||||
A web hook request typically contains a payload, or a request body, made up of a JSON object. The JSON object in the request body will follow a format choosen by the Git server. Thus, it's format will differ depending on whether you are using GitHub, GitLab, Bitbucket or any other Git provider.
|
||||
|
||||
A *payload-filter* can be used to set specific criterias for which incoming web hook requests should actually trigger the deploy command. Filter can be setup to only trigger deploys when a commit is made to a specific branch, or when a pull request is closed and has a specific destination branch.
|
||||
|
||||
Since the format of the payload differs depending on what Git provider you are using, you'll need to inspect the web hook request format yourself and write a filter that matches its structure.
|
||||
|
||||
To specify a filter that should be applied further down the object tree, a dot notation (".") is used. For example, if the request body looks like this;
|
||||
```json
|
||||
{
|
||||
"action": "opened",
|
||||
"number": 69,
|
||||
"pull_request": {
|
||||
"url": "https://api.github.com/repos/olipo186/Git-Auto-Deploy/pulls/69",
|
||||
"id": 61793882,
|
||||
"html_url": "https://github.com/olipo186/Git-Auto-Deploy/pull/69",
|
||||
"diff_url": "https://github.com/olipo186/Git-Auto-Deploy/pull/69.diff",
|
||||
"patch_url": "https://github.com/olipo186/Git-Auto-Deploy/pull/69.patch",
|
||||
"issue_url": "https://api.github.com/repos/olipo186/Git-Auto-Deploy/issues/69",
|
||||
"number": 69,
|
||||
"state": "open",
|
||||
"locked": false,
|
||||
"title": "Refactoring. Fixed some imminent issues.",
|
||||
"user": {
|
||||
"login": "olipo186",
|
||||
"id": 1056476,
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/1056476?v=3",
|
||||
"gravatar_id": "",
|
||||
...
|
||||
},
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
You could specify the following filter, which would only trigger on pull requests created by olipo186.
|
||||
|
||||
```json
|
||||
{
|
||||
...
|
||||
"repositories": [
|
||||
{
|
||||
...
|
||||
"payload-filter": [
|
||||
{
|
||||
"action": "opened",
|
||||
"pull_request.user.login": "olipo186"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## Legacy filters (older format)
|
||||
|
||||
For example, deploy on `push` to the `master` branch only, ignore other branches.
|
||||
|
||||
Filters are defined by providing keys/values to be looked up in the original
|
||||
data sent by the web hook.
|
||||
|
||||
For example, GitLab web hook data looks like this:
|
||||
|
||||
```json
|
||||
{
|
||||
"object_kind":"build",
|
||||
"ref":"master",
|
||||
"tag":false,
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
A filter can use `object_kind` and `ref` attributes for example to execute the
|
||||
deploy action only on a `build` event on the `master` branch.
|
||||
|
||||
### Examples
|
||||
|
||||
#### GitHub
|
||||
|
||||
The following example will trigger when a pull request with **master** as base is closed. The command `./prepull` and `./postpull` will execute immediately before and after the pull
|
||||
```json
|
||||
{
|
||||
"host": "0.0.0.0",
|
||||
"port": 8080,
|
||||
"global_deploy": [
|
||||
"echo Pre-deploy script",
|
||||
"echo Post-deploy script"
|
||||
],
|
||||
"repositories": [
|
||||
{
|
||||
"url": "https://github.com/olipo186/Git-Auto-Deploy.git",
|
||||
"branch": "master",
|
||||
"remote": "origin",
|
||||
"path": "~/repositories/Git-Auto-Deploy",
|
||||
"deploy": "echo deploying",
|
||||
"prepull": "chmod u+w config.json",
|
||||
"postpull": "chmod u-w config.json",
|
||||
"filters": [
|
||||
{
|
||||
"action": "closed",
|
||||
"pull_request": true,
|
||||
"pull_request.base.ref": "master"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
#### GitLab
|
||||
*(Note: the filter examples below are valid for GitLab)*
|
||||
|
||||
Execute pre-deploy script, don't `pull` the repository but execute a deploy
|
||||
script, and finish with a post-deploy script. Execute only for `push` events on
|
||||
the `master` branch.
|
||||
|
||||
```json
|
||||
{
|
||||
"pidfilepath": "~/.gitautodeploy.pid",
|
||||
"host": "0.0.0.0",
|
||||
"port": 8080,
|
||||
"global_deploy": [
|
||||
"echo Pre-deploy script",
|
||||
"echo Post-deploy script"
|
||||
],
|
||||
"repositories": [
|
||||
{
|
||||
"url": "http://gitlab/playground/hooktest.git",
|
||||
"deploy": "echo deploying",
|
||||
"filters": [
|
||||
{
|
||||
"object_kind": "push",
|
||||
"ref": "refs/heads/master"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
Clone repository on `push` to `master`.
|
||||
|
||||
```json
|
||||
{
|
||||
"pidfilepath": "~/.gitautodeploy.pid",
|
||||
"host": "0.0.0.0",
|
||||
"port": 8080,
|
||||
"repositories": [
|
||||
{
|
||||
"url": "http://gitlab/playground/hooktest.git",
|
||||
"branch": "master",
|
||||
"remote": "origin",
|
||||
"path": "~/repositories/hooktest",
|
||||
"filters": [
|
||||
{
|
||||
"object_kind": "push",
|
||||
"ref": "refs/heads/master"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
Execute script upon GitLab CI successful build of `master` branch.
|
||||
|
||||
```json
|
||||
{
|
||||
"pidfilepath": "~/.gitautodeploy.pid",
|
||||
"host": "0.0.0.0",
|
||||
"port": 8080,
|
||||
"global_deploy": [
|
||||
"echo Pre-deploy script",
|
||||
"echo Post-deploy script"
|
||||
],
|
||||
"repositories": [
|
||||
{
|
||||
"url": "http://gitlab/playground/hooktest.git",
|
||||
"deploy": "echo deploying project!",
|
||||
"filters": [
|
||||
{
|
||||
"object_kind": "build",
|
||||
"ref": "master",
|
||||
"build_status": "success"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
#### Bitbucket Server
|
||||
|
||||
Get source using SSH.
|
||||
|
||||
```json
|
||||
{
|
||||
"host": "0.0.0.0",
|
||||
"port": 8080,
|
||||
"global_deploy": [
|
||||
"echo Pre-deploy script",
|
||||
"echo Post-deploy script"
|
||||
],
|
||||
"repositories": [
|
||||
{
|
||||
"url": "ssh://git@bitbucket.example.com/KEY/Git-Auto-Deploy.git",
|
||||
"match-url": "Git-Auto-Deploy",
|
||||
"branch": "master",
|
||||
"remote": "origin",
|
||||
"path": "~/repositories/Git-Auto-Deploy",
|
||||
"deploy": "echo deploying"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
Using HTTPS.
|
||||
|
||||
```json
|
||||
{
|
||||
"host": "0.0.0.0",
|
||||
"port": 8080,
|
||||
"global_deploy": [
|
||||
"echo Pre-deploy script",
|
||||
"echo Post-deploy script"
|
||||
],
|
||||
"repositories": [
|
||||
{
|
||||
"url": "https://bitbucket.example.com/scm/KEY/Git-Auto-Deploy.git",
|
||||
"match-url": "Git-Auto-Deploy",
|
||||
"branch": "master",
|
||||
"remote": "origin",
|
||||
"path": "~/repositories/Git-Auto-Deploy",
|
||||
"deploy": "echo deploying"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
```
|
||||
|
||||
# Repository configuration using environment variables
|
||||
|
||||
It's possible to configure up to one repository using environment variables. This can be useful in some specific use cases where a full config file is undesired.
|
||||
|
||||
Environment variable | Description
|
||||
-------------------- | --------------------------
|
||||
GAD_REPO_URL | Repository URL
|
||||
GAD_REPO_BRANCH |
|
||||
GAD_REPO_REMOTE |
|
||||
GAD_REPO_PATH | Path to where ```Git-Auto-Deploy``` should clone and pull repository
|
||||
GAD_REPO_DEPLOY | Deploy command
|
@ -0,0 +1,23 @@
|
||||
# Continuous Delivery via Pull requests (GitHub only)
|
||||
|
||||
![Workflow](./graphics/continuous_delivery_process.png)
|
||||
|
||||
If you use continious delivery (such as this workflow) you may want to trigger deploy event when pull request is opened or closed.
|
||||
You can follow next steps to implement CD process:
|
||||
* Set repo "url" to ```"https://api.github.com"```
|
||||
* Add filter type "pull-request-filter" as described below
|
||||
* Configure "action" that you want to listen
|
||||
* Configure branch in which pull request trying to merge (variable "ref" below)
|
||||
|
||||
Example
|
||||
```json
|
||||
"url": "https://api.github.com/repos/olipo186/Git-Auto-Deploy",
|
||||
"deploy": "echo deploying after pull request",
|
||||
"filters": [
|
||||
{
|
||||
"action": "closed",
|
||||
"pull_request": true,
|
||||
"pull_request.base.ref": "testing-branch"
|
||||
}
|
||||
]
|
||||
```
|
@ -0,0 +1,51 @@
|
||||
# Install as debian package from PPA (experimental)
|
||||
|
||||
Add our PPA
|
||||
|
||||
add-apt-repository ppa:olipo186/git-auto-deploy
|
||||
apt-get update
|
||||
|
||||
Install the package
|
||||
|
||||
apt-get install git-auto-deploy
|
||||
|
||||
Make your changes to the configuration file
|
||||
|
||||
nano /etc/git-auto-deploy.conf.json
|
||||
|
||||
Run the application
|
||||
|
||||
service git-auto-deploy start
|
||||
service git-auto-deploy status
|
||||
|
||||
# Install from .deb file (experimental)
|
||||
|
||||
Below is instructions on how to create a debian (.deb) package using stdeb. You can follow the instructions below to build the .deb package, or use the prepared script (platforms/debian/scripts/create-debian-package.sh) that will do the same. Once the package is created, you can install it using ```dpkg -i```. A sample configuration file as well as a init.d start up script will be installed as part of the package.
|
||||
|
||||
### Install dependencies
|
||||
|
||||
Install stdeb and other dependencies
|
||||
|
||||
apt-get install python-stdeb fakeroot python-all
|
||||
|
||||
### Download and build
|
||||
|
||||
git clone https://github.com/olipo186/Git-Auto-Deploy.git
|
||||
cd Git-Auto-Deploy
|
||||
make deb
|
||||
|
||||
### Install
|
||||
|
||||
When installing the package, a sample configuration file and a init.d start up script will be created.
|
||||
|
||||
dpkg -i dist/deb/git-auto-deploy-<version>.deb
|
||||
|
||||
### Configuration
|
||||
|
||||
nano /etc/git-auto-deploy.conf.json
|
||||
|
||||
### Running the application
|
||||
|
||||
service git-auto-deploy start
|
||||
service git-auto-deploy status
|
||||
|
@ -0,0 +1,41 @@
|
||||
# Install as a python module (experimental)
|
||||
|
||||
## Download and install
|
||||
|
||||
Install using [pip](http://www.pip-installer.org/en/latest/), a package manager for Python, by running the following command.
|
||||
|
||||
pip install git-auto-deploy
|
||||
|
||||
If you don't have pip installed, try installing it by running this from the command
|
||||
line:
|
||||
|
||||
curl https://raw.github.com/pypa/pip/master/contrib/get-pip.py | python
|
||||
|
||||
Or, you can [download the source code
|
||||
(ZIP)](https://github.com/olipo186/Git-Auto-Deploy/zipball/master "Git-Auto-Deploy
|
||||
source code") for `Git-Auto-Deploy` and then run:
|
||||
|
||||
python setup.py install
|
||||
|
||||
You may need to run the above commands with `sudo`.
|
||||
|
||||
Once ```Git-Auto-Deploy``` has been installed as a python module, it can be started using the executable ```git-auto-deploy```. During installation with pip, the executable is usually installed in ```/usr/local/bin/git-auto-deploy```. This can vary depending on platform.
|
||||
|
||||
## Configuration
|
||||
|
||||
Copy the content of [config.json.sample](../config.json.sample) and save it anywhere you like, for example ```~/git-auto-deploy.conf.json```. Modify it to match your project setup. [Read more about the configuration options](../docs/Configuration.md).
|
||||
|
||||
## Running the application
|
||||
|
||||
Run the application using the executable ```git-auto-deploy``` which has been provided by pip. Provide the path to your configuration file as a command line argument.
|
||||
|
||||
git-auto-deploy --config ~/git-auto-deploy.conf.json
|
||||
|
||||
## Start automatically on boot using crontab
|
||||
|
||||
The easiest way to configure your system to automatically start ```Git-Auto-Deploy``` after a reboot is using crontab. Open crontab in edit mode using ```crontab -e``` and add the entry below.
|
||||
|
||||
When installing with pip, the executable ```git-auto-deploy``` is usually installed in ```/usr/local/bin/git-auto-deploy```. It is a good idea to verify the path to ```git-auto-deploy``` before adding the entry below.
|
||||
|
||||
@reboot /usr/local/bin/git-auto-deploy --daemon-mode --quiet --config /path/to/git-auto-deploy.conf.json
|
||||
|
@ -0,0 +1,14 @@
|
||||
# Git-Auto-Deploy documentation
|
||||
|
||||
# Documents
|
||||
|
||||
* [Configuration options](./Configuration.md)
|
||||
* [Install as a python module (experimental)](./Install as a python module.md)
|
||||
* [Install as a debian package (experimental)](./Install as a debian package.md)
|
||||
* [Start automatically on boot (init.d and systemd)](./Start automatically on boot.md)
|
||||
|
||||
# Example workflows
|
||||
|
||||
## Continuous Delivery via Pull requests (GitHub only)
|
||||
|
||||
It's possible to configure Git-Auto-Deploy to trigger when pull requests are opened or closed on GitHub. To read more about this workflow and how to configure Git-Aut-Deploy here: [Continuous Delivery via Pull requests](./Continuous Delivery via Pull requests.md)
|
@ -0,0 +1,70 @@
|
||||
# Start automatically on boot
|
||||
|
||||
```Git-Auto-Deploy``` can be automatically started at boot time using various techniques. Below you'll find a couple of suggested approaches with instructions.
|
||||
|
||||
The following instructions assumes that you are running ```Git-Auto-Deploy``` from a clone of this repository. In such a case, ```Git-Auto-Deploy``` is started by invoking ```python -m``` and referencing the ```gitautodeploy``` python module which is found in the cloned repository. Such a command can look like ```python -m /path/to/Git-Auto-Deploy/gitautodeploy --daemon-mode```.
|
||||
|
||||
If you have used any of the alternative installation methods (install with pip or as a debian package), you will instead start ```Git-Auto-Deploy``` using a installed executable. ```Git-Auto-Deploy``` would then be started using a command like ```git-auto-deploy --daemon-mode``` instead. If you have installed ```Git-Auto-Deploy``` in this way, you will need to modify the paths and commands used in the instructions below.
|
||||
|
||||
## Crontab
|
||||
The easiest way to configure your system to automatically start ```Git-Auto-Deploy``` after a reboot is using crontab. Open crontab in edit mode using ```crontab -e``` and add the following:
|
||||
|
||||
@reboot /usr/bin/python -m /path/to/Git-Auto-Deploy/gitautodeploy --daemon-mode --quiet
|
||||
|
||||
## Debian and Sys-V like init system.
|
||||
|
||||
Copy the sample init script into ```/etc/init.d/``` and make it executable.
|
||||
|
||||
cp platforms/linux/initfiles/debianLSBInitScripts/git-auto-deploy /etc/init.d/
|
||||
chmod 755 /etc/init.d/git-auto-deploy
|
||||
|
||||
**Important:** The init script assumes that you have ```Git-Auto-Deploy``` installed in ```/opt/Git-Auto-Deploy/``` and that the ```pidfilepath``` config option is set to ```/var/run/git-auto-deploy.pid```. If this is not the case, edit the ```git-auto-deploy``` init script and modify ```DAEMON```, ```PWD``` and ```PIDFILE```.
|
||||
|
||||
**Important:** The init script will run GAD as the ```root``` user by default, which is convenient but not secure. The recommended way to run GAD is to set up a separate user and modify the init script to run GAD as that user. When running GAD as a user other than root, you will need to make sure that the correct permissions are set on all directories and files that GAD requires access to (such as the path specified in the variable PIDFILE and LOGFIE in the init script).
|
||||
|
||||
Now you need to add the correct symbolic link to your specific runlevel dir to get the script executed on each start up. On Debian_Sys-V just do;
|
||||
|
||||
update-rc.d git-auto-deploy defaults
|
||||
|
||||
Fire it up and verify;
|
||||
|
||||
service git-auto-deploy start
|
||||
service git-auto-deploy status
|
||||
|
||||
## Systemd
|
||||
|
||||
Copy the sample systemd service file ```git-auto-deploy.service``` into ```/etc/systemd/system```;
|
||||
|
||||
cp platforms/linux/initfiles/systemd/git-auto-deploy.service /etc/systemd/system
|
||||
|
||||
Create the user and group specified in git-auto-deploy.service (```www-data```) if those do not exist already.
|
||||
|
||||
useradd -U www-data
|
||||
|
||||
This init script assumes that you have ```Git-Auto-Deploy``` installed in ```/opt/Git-Auto-Deploy/```. If this is not the case, edit the ```git-auto-deploy.service``` service file and modify ```ExecStart``` and ```WorkingDirectory```.
|
||||
|
||||
Now, reload daemons and fire ut up;
|
||||
|
||||
systemctl daemon-reload
|
||||
systemctl start git-auto-deploy
|
||||
|
||||
Make is start automatically on system boot;
|
||||
|
||||
systemctl enable gitautodeploy
|
||||
|
||||
## CentOS 7
|
||||
|
||||
Have a look at [this script](../platforms/linux/initfiles/centos) which was kindly provided by https://github.com/olipo186/Git-Auto-Deploy/issues/192. Usage:
|
||||
|
||||
Start:
|
||||
|
||||
GitAutoDeploy_Service.sh start
|
||||
|
||||
Stop:
|
||||
|
||||
GitAutoDeploy_Service.sh stop
|
||||
|
||||
Stop:
|
||||
|
||||
GitAutoDeploy_Service.sh restart
|
||||
|
@ -0,0 +1,22 @@
|
||||
# How to add your SSH keys to Git-Auto-Deploy
|
||||
|
||||
1. Copy your ssh keys from your account to /etc/git-auto-deploy/.ssh/
|
||||
|
||||
```cp -R ~/.ssh /etc/git-auto-deploy/```
|
||||
|
||||
2. Add gitlab, github or your hostname to the known_hosts file, eg.
|
||||
|
||||
```ssh-keyscan -t rsa gitlab.com >> /etc/git-auto-deploy/.ssh/known_hosts```
|
||||
|
||||
3. Add read and write permissions to /etc/git-auto-deploy
|
||||
|
||||
```
|
||||
chown -R git-auto-deploy:git-auto-deploy /etc/git-auto-deploy
|
||||
chmod -R 700 /etc/git-auto-deploy/.ssh/*
|
||||
```
|
||||
|
||||
4. Add write permissions to your repository path
|
||||
|
||||
```chown -R git-auto-deploy:git-auto-deploy /home/myrepo```
|
||||
|
||||
Make sure you use your ssh url in your config.
|
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 48 KiB |
@ -0,0 +1,5 @@
|
||||
from __future__ import absolute_import
|
||||
|
||||
from .gitautodeploy import *
|
||||
from .cli import *
|
||||
from .parsers import *
|
@ -0,0 +1,17 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
if __package__ != 'gitautodeploy':
|
||||
import sys
|
||||
print("Critical - GAD must be started as a python module, for example using python -m gitautodeploy")
|
||||
sys.exit()
|
||||
|
||||
from gitautodeploy import main
|
||||
import sys
|
||||
import os
|
||||
sys.path.insert(0, os.path.dirname(os.path.realpath(__file__)))
|
||||
main()
|
||||
|
||||
else:
|
||||
from gitautodeploy import main
|
@ -0,0 +1 @@
|
||||
from .config import *
|
@ -0,0 +1,503 @@
|
||||
class ConfigFileNotFoundException(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class ConfigFileInvalidException(Exception):
|
||||
pass
|
||||
|
||||
|
||||
def get_config_defaults():
|
||||
"""Get the default configuration values."""
|
||||
|
||||
config = {}
|
||||
|
||||
# Supress console output
|
||||
config['quiet'] = False
|
||||
|
||||
# Run in daemon mode
|
||||
config['daemon-mode'] = False
|
||||
|
||||
# File containing additional config options
|
||||
config['config'] = None
|
||||
|
||||
# File to store a copy of the console output
|
||||
config['log-file'] = None
|
||||
|
||||
# File to store the process id (pid)
|
||||
config['pid-file'] = '~/.gitautodeploy.pid'
|
||||
|
||||
# HTTP server options
|
||||
config['http-enabled'] = True
|
||||
config['http-host'] = '0.0.0.0'
|
||||
config['http-port'] = 8001
|
||||
|
||||
# HTTPS server options
|
||||
config['https-enabled'] = True
|
||||
config['https-host'] = '0.0.0.0'
|
||||
config['https-port'] = 8002
|
||||
|
||||
# Web socket server options (used by web UI for real time updates)
|
||||
config['wss-enabled'] = False # Disabled by default until authentication is in place
|
||||
config['wss-host'] = '0.0.0.0'
|
||||
config['wss-port'] = 8003
|
||||
|
||||
# TLS/SSL cert (necessary for HTTPS and web socket server to work)
|
||||
config['ssl-key'] = None # If specified, holds the private key
|
||||
config['ssl-cert'] = '~/cert.pem' # Holds the public key or both the private and public keys
|
||||
|
||||
# Web user interface options
|
||||
config['web-ui-enabled'] = False # Disabled by default until authentication is in place
|
||||
config['web-ui-username'] = None
|
||||
config['web-ui-password'] = None
|
||||
config['web-ui-whitelist'] = ['127.0.0.1']
|
||||
config['web-ui-require-https'] = True
|
||||
config['web-ui-auth-enabled'] = True
|
||||
config['web-ui-prevent-root'] = True
|
||||
|
||||
# Record all log levels by default
|
||||
config['log-level'] = 'NOTSET'
|
||||
|
||||
# Other options
|
||||
config['intercept-stdout'] = True
|
||||
config['ssh-keyscan'] = False
|
||||
config['allow-root-user'] = False
|
||||
|
||||
# Log incoming webhook requests in a way they can be used as test cases
|
||||
config['log-test-case'] = False
|
||||
config['log-test-case-dir'] = None
|
||||
|
||||
return config
|
||||
|
||||
|
||||
def rename_legacy_attribute_names(config):
|
||||
import logging
|
||||
logger = logging.getLogger()
|
||||
|
||||
rewrite_map = {
|
||||
'ssl': 'https-enabled',
|
||||
'ssl-pem-file': 'ssl-cert',
|
||||
'host': 'http-host',
|
||||
'port': 'http-port',
|
||||
'pidfilepath': 'pid-file',
|
||||
'logfilepath': 'log-file'
|
||||
}
|
||||
|
||||
for item in rewrite_map.items():
|
||||
old_name, new_name = item
|
||||
if old_name in config:
|
||||
config[new_name] = config[old_name]
|
||||
del config[old_name]
|
||||
print("Config option '%s' is deprecated. Please use '%s' instead." % (old_name, new_name))
|
||||
|
||||
return config
|
||||
|
||||
|
||||
def get_config_from_environment():
|
||||
"""Get configuration values provided as environment variables."""
|
||||
import os
|
||||
|
||||
config = {}
|
||||
|
||||
if 'GAD_QUIET' in os.environ:
|
||||
config['quiet'] = True
|
||||
|
||||
if 'GAD_DAEMON_MODE' in os.environ:
|
||||
config['daemon-mode'] = True
|
||||
|
||||
if 'GAD_CONFIG' in os.environ:
|
||||
config['config'] = os.environ['GAD_CONFIG']
|
||||
|
||||
if 'GAD_SSH_KEYSCAN' in os.environ:
|
||||
config['ssh-keyscan'] = True
|
||||
|
||||
if 'GAD_SSL_KEY' in os.environ:
|
||||
config['ssl-key'] = os.environ['GAD_SSL_KEY']
|
||||
|
||||
if 'GAD_SSL_CERT' in os.environ:
|
||||
config['ssl-cert'] = os.environ['GAD_SSL_CERT']
|
||||
|
||||
if 'GAD_PID_FILE' in os.environ:
|
||||
config['pid-file'] = os.environ['GAD_PID_FILE']
|
||||
|
||||
if 'GAD_LOG_FILE' in os.environ:
|
||||
config['log-file'] = os.environ['GAD_LOG_FILE']
|
||||
|
||||
if 'GAD_HOST' in os.environ:
|
||||
config['http-host'] = os.environ['GAD_HOST']
|
||||
|
||||
if 'GAD_HTTP_HOST' in os.environ:
|
||||
config['http-host'] = os.environ['GAD_HTTP_HOST']
|
||||
|
||||
if 'GAD_HTTPS_HOST' in os.environ:
|
||||
config['https-host'] = os.environ['GAD_HTTPS_HOST']
|
||||
|
||||
if 'GAD_PORT' in os.environ:
|
||||
config['http-port'] = int(os.environ['GAD_PORT'])
|
||||
|
||||
if 'GAD_HTTP_PORT' in os.environ:
|
||||
config['http-port'] = int(os.environ['GAD_HTTP_PORT'])
|
||||
|
||||
if 'GAD_HTTPS_PORT' in os.environ:
|
||||
config['https-port'] = int(os.environ['GAD_HTTPS_PORT'])
|
||||
|
||||
return config
|
||||
|
||||
|
||||
def get_config_from_argv(argv):
|
||||
import argparse
|
||||
|
||||
parser = argparse.ArgumentParser()
|
||||
|
||||
parser.add_argument("-d", "--daemon-mode",
|
||||
help="run in background (daemon mode)",
|
||||
dest="daemon-mode",
|
||||
default=None,
|
||||
action="store_true")
|
||||
|
||||
parser.add_argument("-q", "--quiet",
|
||||
help="supress console output",
|
||||
dest="quiet",
|
||||
default=None,
|
||||
action="store_true")
|
||||
|
||||
parser.add_argument("-c", "--config",
|
||||
help="custom configuration file",
|
||||
dest="config",
|
||||
type=str)
|
||||
|
||||
parser.add_argument("--ssh-keyscan",
|
||||
help="scan repository hosts for ssh keys",
|
||||
dest="ssh-keyscan",
|
||||
default=None,
|
||||
action="store_true")
|
||||
|
||||
parser.add_argument("--pid-file",
|
||||
help="specify a custom pid file",
|
||||
dest="pid-file",
|
||||
type=str)
|
||||
|
||||
parser.add_argument("--log-file",
|
||||
help="specify a log file",
|
||||
dest="log-file",
|
||||
type=str)
|
||||
|
||||
parser.add_argument("--log-level",
|
||||
help="specify log level",
|
||||
dest="log-level",
|
||||
type=str)
|
||||
|
||||
parser.add_argument("--host",
|
||||
help="address to bind http server to",
|
||||
dest="http-host",
|
||||
type=str)
|
||||
|
||||
#parser.add_argument("--http-host",
|
||||
# help="address to bind http server to",
|
||||
# dest="http-host",
|
||||
# type=str)
|
||||
|
||||
#parser.add_argument("--https-host",
|
||||
# help="address to bind https server to",
|
||||
# dest="https-host",
|
||||
# type=str)
|
||||
|
||||
parser.add_argument("--port",
|
||||
help="port to bind http server to",
|
||||
dest="http-port",
|
||||
type=int)
|
||||
|
||||
#parser.add_argument("--http-port",
|
||||
# help="port to bind http server to",
|
||||
# dest="http-port",
|
||||
# type=int)
|
||||
|
||||
#parser.add_argument("--https-port",
|
||||
# help="port to bind http server to",
|
||||
# dest="https-port",
|
||||
# type=int)
|
||||
|
||||
parser.add_argument("--ws-port",
|
||||
help="port to bind web socket server to",
|
||||
dest="web-ui-web-socket-port",
|
||||
type=int)
|
||||
|
||||
parser.add_argument("--ssl",
|
||||
help="enable https",
|
||||
dest="https-enabled",
|
||||
default=None,
|
||||
action="store_true")
|
||||
|
||||
parser.add_argument("--ssl-key",
|
||||
help="path to ssl key file",
|
||||
dest="ssl-key",
|
||||
type=str)
|
||||
|
||||
parser.add_argument("--ssl-cert",
|
||||
help="path to ssl cert file",
|
||||
dest="ssl-cert",
|
||||
type=str)
|
||||
|
||||
parser.add_argument("--allow-root-user",
|
||||
help="allow running as root user",
|
||||
dest="allow-root-user",
|
||||
default=None,
|
||||
action="store_true")
|
||||
|
||||
|
||||
config = vars(parser.parse_args(argv))
|
||||
|
||||
# Delete entries for unprovided arguments
|
||||
del_keys = []
|
||||
for key in config:
|
||||
if config[key] is None:
|
||||
del_keys.append(key)
|
||||
|
||||
for key in del_keys:
|
||||
del config[key]
|
||||
|
||||
return config
|
||||
|
||||
|
||||
def find_config_file(target_directories=None):
|
||||
"""Attempt to find a path to a config file. Provided paths are scanned
|
||||
for *.conf(ig)?.json files."""
|
||||
import os
|
||||
import re
|
||||
import logging
|
||||
logger = logging.getLogger()
|
||||
|
||||
if not target_directories:
|
||||
return
|
||||
|
||||
# Remove duplicates
|
||||
target_directories = list(set(target_directories))
|
||||
|
||||
# Look for a *conf.json or *config.json
|
||||
for dir in target_directories:
|
||||
|
||||
if not os.access(dir, os.R_OK):
|
||||
continue
|
||||
|
||||
for item in os.listdir(dir):
|
||||
if re.match(r".*conf(ig)?\.json$", item):
|
||||
path = os.path.realpath(os.path.join(dir, item))
|
||||
logger.info("Using '%s' as config" % path)
|
||||
return path
|
||||
|
||||
|
||||
def get_config_from_file(path):
|
||||
"""Get configuration values from config file."""
|
||||
import logging
|
||||
import os
|
||||
logger = logging.getLogger()
|
||||
|
||||
config_file_path = os.path.realpath(path)
|
||||
logger.info('Using custom configuration file \'%s\'' % config_file_path)
|
||||
|
||||
# Read config data from json file
|
||||
if config_file_path:
|
||||
config_data = read_json_file(config_file_path)
|
||||
else:
|
||||
logger.info('No configuration file found or specified. Using default values.')
|
||||
config_data = {}
|
||||
|
||||
return config_data
|
||||
|
||||
|
||||
def read_json_file(file_path):
|
||||
import json
|
||||
import logging
|
||||
import re
|
||||
import errno
|
||||
|
||||
try:
|
||||
json_string = open(file_path).read()
|
||||
|
||||
except IOError as e:
|
||||
if e.errno == errno.ENOENT:
|
||||
raise ConfigFileNotFoundException(file_path)
|
||||
else:
|
||||
raise e
|
||||
|
||||
except Exception as e:
|
||||
raise e
|
||||
|
||||
try:
|
||||
# Remove commens from JSON (makes sample config options easier)
|
||||
regex = r'\s*(#|\/{2}).*$'
|
||||
regex_inline = r'(:?(?:\s)*([A-Za-z\d\.{}]*)|((?<=\").*\"),?)(?:\s)*(((#|(\/{2})).*)|)$'
|
||||
lines = json_string.split('\n')
|
||||
|
||||
for index, line in enumerate(lines):
|
||||
if re.search(regex, line):
|
||||
if re.search(r'^' + regex, line, re.IGNORECASE):
|
||||
lines[index] = ""
|
||||
elif re.search(regex_inline, line):
|
||||
lines[index] = re.sub(regex_inline, r'\1', line)
|
||||
|
||||
data = json.loads('\n'.join(lines))
|
||||
|
||||
except ValueError as e:
|
||||
raise ConfigFileInvalidException(file_path)
|
||||
|
||||
except Exception as e:
|
||||
raise e
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def init_config(config):
|
||||
"""Initialize config by filling out missing values etc."""
|
||||
|
||||
import os
|
||||
import re
|
||||
import logging
|
||||
from ..models import Project
|
||||
logger = logging.getLogger()
|
||||
|
||||
# Translate any ~ in the path into /home/<user>
|
||||
if 'pid-file' in config and config['pid-file']:
|
||||
config['pid-file'] = os.path.expanduser(config['pid-file'])
|
||||
|
||||
if 'log-file' in config and config['log-file']:
|
||||
config['log-file'] = os.path.expanduser(config['log-file'])
|
||||
|
||||
if 'ssl-cert' in config and config['ssl-cert']:
|
||||
config['ssl-cert'] = os.path.expanduser(config['ssl-cert'])
|
||||
|
||||
if 'ssl-key' in config and config['ssl-key']:
|
||||
config['ssl-key'] = os.path.expanduser(config['ssl-key'])
|
||||
|
||||
if 'repositories' not in config:
|
||||
config['repositories'] = []
|
||||
|
||||
deserialized = []
|
||||
|
||||
for repo_config in config['repositories']:
|
||||
|
||||
# Setup branch if missing
|
||||
if 'branch' not in repo_config:
|
||||
repo_config['branch'] = "master"
|
||||
|
||||
# Setup remote if missing
|
||||
if 'remote' not in repo_config:
|
||||
repo_config['remote'] = "origin"
|
||||
|
||||
# Setup deploy commands list if not present
|
||||
if 'deploy_commands' not in repo_config:
|
||||
repo_config['deploy_commands'] = []
|
||||
|
||||
# Check if any global pre deploy commands is specified
|
||||
if 'global_deploy' in config and len(config['global_deploy']) > 0 and len(config['global_deploy'][0]) is not 0:
|
||||
repo_config['deploy_commands'].insert(0, config['global_deploy'][0])
|
||||
|
||||
# Check if any repo specific deploy command is specified
|
||||
if 'deploy' in repo_config:
|
||||
repo_config['deploy_commands'].append(repo_config['deploy'])
|
||||
|
||||
# Check if any global post deploy command is specified
|
||||
if 'global_deploy' in config and len(config['global_deploy']) > 1 and len(config['global_deploy'][1]) is not 0:
|
||||
repo_config['deploy_commands'].append(config['global_deploy'][1])
|
||||
|
||||
# If a repository is configured with embedded credentials, we create an alternate URL
|
||||
# without these credentials that cen be used when comparing the URL with URLs referenced
|
||||
# in incoming web hook requests.
|
||||
if 'url' in repo_config:
|
||||
regexp = re.search(r"^(https?://)([^@]+)@(.+)$", repo_config['url'])
|
||||
if regexp:
|
||||
repo_config['url_without_usernme'] = regexp.group(1) + regexp.group(3)
|
||||
|
||||
# Translate any ~ in the path into /home/<user>
|
||||
if 'path' in repo_config:
|
||||
repo_config['path'] = os.path.expanduser(repo_config['path'])
|
||||
|
||||
# Support for legacy config format
|
||||
if 'filters' in repo_config:
|
||||
repo_config['payload-filter'] = repo_config['filters']
|
||||
del repo_config['filters']
|
||||
|
||||
if 'payload-filter' not in repo_config:
|
||||
repo_config['payload-filter'] = []
|
||||
|
||||
if 'header-filter' not in repo_config:
|
||||
repo_config['header-filter'] = {}
|
||||
|
||||
# Rewrite some legacy filter config syntax
|
||||
for filter in repo_config['payload-filter']:
|
||||
|
||||
# Legacy config syntax?
|
||||
if ('kind' in filter and filter['kind'] == 'pull-request-handler') or ('type' in filter and filter['type'] == 'pull-request-filter'):
|
||||
|
||||
# Reset legacy values
|
||||
filter['kind'] = None
|
||||
filter['type'] = None
|
||||
|
||||
if 'ref' in filter:
|
||||
filter['pull_request.base.ref'] = filter['ref']
|
||||
filter['ref'] = None
|
||||
|
||||
filter['pull_request'] = True
|
||||
|
||||
project = Project(repo_config)
|
||||
deserialized.append(project)
|
||||
|
||||
config['repositories'] = deserialized
|
||||
|
||||
return config
|
||||
|
||||
|
||||
def get_repo_config_from_environment():
|
||||
"""Look for repository config in any defined environment variables. If
|
||||
found, import to main config."""
|
||||
import logging
|
||||
import os
|
||||
|
||||
if 'GAD_REPO_URL' not in os.environ:
|
||||
return
|
||||
|
||||
logger = logging.getLogger()
|
||||
|
||||
repo_config = {
|
||||
'url': os.environ['GAD_REPO_URL']
|
||||
}
|
||||
|
||||
logger.info("Added configuration for '%s' found in environment variables" % os.environ['GAD_REPO_URL'])
|
||||
|
||||
if 'GAD_REPO_BRANCH' in os.environ:
|
||||
repo_config['branch'] = os.environ['GAD_REPO_BRANCH']
|
||||
|
||||
if 'GAD_REPO_REMOTE' in os.environ:
|
||||
repo_config['remote'] = os.environ['GAD_REPO_REMOTE']
|
||||
|
||||
if 'GAD_REPO_PATH' in os.environ:
|
||||
repo_config['path'] = os.environ['GAD_REPO_PATH']
|
||||
|
||||
if 'GAD_REPO_DEPLOY' in os.environ:
|
||||
repo_config['deploy'] = os.environ['GAD_REPO_DEPLOY']
|
||||
|
||||
return repo_config
|
||||
|
||||
|
||||
def get_config_file_path(env_config, argv_config, search_target):
|
||||
import os
|
||||
|
||||
# Config file path provided in argument vector?
|
||||
if 'config' in argv_config and argv_config['config']:
|
||||
config_file_path = os.path.realpath(argv_config['config'])
|
||||
|
||||
# Config file path provided in environment variable?
|
||||
elif 'config' in env_config and env_config['config']:
|
||||
config_file_path = os.path.realpath(env_config['config'])
|
||||
|
||||
# Search file system
|
||||
else:
|
||||
|
||||
# Directories to scan for config files
|
||||
target_directories = [
|
||||
os.getcwd(), # cwd
|
||||
search_target # script path
|
||||
]
|
||||
|
||||
config_file_path = find_config_file(target_directories)
|
||||
|
||||
return config_file_path
|
@ -0,0 +1,64 @@
|
||||
{
|
||||
// HTTP server options
|
||||
//"http-enabled": true,
|
||||
//"http-host": "0.0.0.0",
|
||||
//"http-port": 8001,
|
||||
|
||||
// HTTPS server options
|
||||
//"https-enabled": true,
|
||||
//"https-host": "0.0.0.0",
|
||||
//"https-port": 8002,
|
||||
|
||||
// Web socket server options (used by web UI for real time updates)
|
||||
//"wss-enabled": false,
|
||||
//"wss-host": "0.0.0.0",
|
||||
//"wss-port": 8003,
|
||||
|
||||
// Web user interface options
|
||||
//"web-ui-enabled": false,
|
||||
//"web-ui-username": null,
|
||||
//"web-ui-password": null,
|
||||
//"web-ui-whitelist": ["127.0.0.1"],
|
||||
|
||||
// TLS/SSL cert (ne |