Skip to content

Commit

Permalink
Merge branch 'release/2.7.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
genebean committed Dec 30, 2019
2 parents 6e73048 + a8cf0ea commit 8b58e1c
Show file tree
Hide file tree
Showing 5 changed files with 130 additions and 10 deletions.
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ sudo: required
language: ruby
cache: bundler
rvm:
- 2.6.0
- 2.7

services:
- docker
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM ruby:2.6.5-slim-buster
FROM ruby:2.7.0-slim-buster

LABEL maintainer "[email protected]"

Expand Down
6 changes: 4 additions & 2 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,10 @@ GEM
builder
minitest (>= 5.0)
ruby-progressbar
mustermann (1.0.3)
mustermann (1.1.0)
ruby2_keywords (~> 0.0.1)
parallel (1.19.1)
parser (2.6.5.0)
parser (2.7.0.1)
ast (~> 2.4.0)
passenger (6.0.4)
rack
Expand All @@ -37,6 +38,7 @@ GEM
rubocop-performance (1.5.2)
rubocop (>= 0.71.0)
ruby-progressbar (1.10.1)
ruby2_keywords (0.0.1)
sinatra (2.0.7)
mustermann (~> 1.0)
rack (~> 2.0)
Expand Down
101 changes: 98 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,24 @@

tree-planter is a webhook receiver that is designed to deploy code trees via either a simple JSON payload or the payload from a GitLab webhook. Cloned branches can also be deleted via a the GitLab webhook.

Technology-wise, tree-planter is a Ruby application built on [Sinatra][sinatra]. The application is served up by the [Passenger][passenger] gem. All this has been neatly wrapped up in a Docker container that's based on the official [ruby:2.6-slim-buster][ruby] one which, in turn, is based on the official [debian:buster][debian] one. A utility called [gosu][gosu] is used for the entry point so that the application can run with a specified UID.
Technology-wise, tree-planter is a Ruby application built on [Sinatra][sinatra]. The application is served up by the [Passenger][passenger] gem. All this has been neatly wrapped up in a Docker container that's based on the official [ruby:2.7-slim-buster][ruby] one which, in turn, is based on the official [debian:buster][debian] one. A utility called [gosu][gosu] is used for the entry point so that the application can run with a specified UID.

- [File ownership / permissions](#file-ownership--permissions)
- [Running the container](#running-the-container)
- [And here it is all together](#and-here-it-is-all-together)
- [End Points](#end-points)
- [Examples](#examples)
- [Metrics](#metrics)
- [Triggering the /deploy endpoint via cURL](#triggering-the-deploy-endpoint-via-curl)
- [Triggering the /gitlab endpoint via cURL with a GitLab-like payload](#triggering-the-gitlab-endpoint-via-curl-with-a-gitlab-like-payload)
- [Clone a branch into an alternate destination path](#clone-a-branch-into-an-alternate-destination-path)
- [Delete cloned copy of feature/parsable_names branch with a GitLab-like payload](#delete-cloned-copy-of-featureparsablenames-branch-with-a-gitlab-like-payload)
- [Delete cloned copy of feature/parsable_names branch with a GitLab-like payload](#delete-cloned-copy-of-featureparsable_names-branch-with-a-gitlab-like-payload)
- [Updating Gemfile.lock](#updating-gemfilelock)
- [Development & Testing](#development-amp-testing)
- [Vagrant](#vagrant)
- [Manual testing](#manual-testing)
- [Validation](#validation)
- [Don't forget](#dont-forget)

## File ownership / permissions

Expand Down Expand Up @@ -198,6 +203,23 @@ If using the Vagrant box or running behind Apache on your server these will all

## Examples

### Metrics

Both stock metrics provided by integrating with Rack and custom metrics are available via the `/metrics` endpoint. Here is a sample of what you should see there:

```plain
# TYPE tree_deploys counter
# HELP tree_deploys A count of how many times each variation of each tree has been deployed
tree_deploys{tree_name="tree-planter",branch_name="master",repo_path="tree-planter",endpoint="deploy"} 3.0
tree_deploys{tree_name="tree-planter",branch_name="master",repo_path="tree-planter___master",endpoint="gitlab"} 2.0
# TYPE http_server_requests_total counter
# HELP http_server_requests_total The total number of HTTP requests handled by the Rack application.
http_server_requests_total{code="200",method="head",path="/"} 1.0
http_server_requests_total{code="200",method="get",path="/metrics"} 3.0
http_server_requests_total{code="200",method="post",path="/deploy"} 3.0
http_server_requests_total{code="200",method="post",path="/gitlab"} 2.0
```

### Triggering the `/deploy` endpoint via cURL

```bash
Expand Down Expand Up @@ -291,13 +313,86 @@ http://localhost/gitlab

## Development & Testing

### Vagrant

The repository contains a Vagrantfile that will allow you to fire up a CentOS 7 box that contains the Puppet agent. It builds and deploys the Docker image using the tools documented above. After it is up you can talk to the container in four ways:

1. Run `curl` commands from inside the Vagrant box targeted at http://localhost
2. Run `curl` or a similar command from the command prompt / terminal of your local computer targeted at http://localhost:8080
3. Run `vagrant share` and then target an endpoint such as http://caring-orangutan-0713.vagrantshare.com/gitlab You can learn more about Vagrant Share [here][vs].
4. Run [ngrok][ngrok] on your local computer by executing `./ngrok http 8080` and then targeting an endpoint such as http://2bf16064.ngrok.io/gitlab (adapt the URL based on ngrok's output)

### Manual testing

You can then easily rebuild and test your code by stopping the puppet-created service and using docker directly like so:

```bash
sudo systemctl stop docker-johnny_appleseed
cd /vagrant
docker build -t genebean/tree-planter .
docker run --rm -p 80:8080 -v /home/vagrant/.ssh/vagrant_priv_key:/home/user/.ssh/id_rsa -v /home/vagrant/trees:/opt/trees -v /var/log/tree-planter:/var/www/tree-planter/log -e LOCAL_USER_ID=1000
```

Depending on your changes, you may also need to clean up what currently exists:

```bash
# clean most things
docker system prune -f

# clean all the things
docker system prune -fa
```

### Validation

Once you think everything is good you should re-run puppet to update its setup and then re-run the tests done during `vagrant up`:

```bash
sudo -i puppet apply /vagrant/docker.pp

docker exec johnny_appleseed /bin/sh -c 'bundle exec rake test'

sudo rm -rf /home/vagrant/trees/tree-planter*

curl -H "Content-Type: application/json" -X POST -d \
'{"ref":"refs/heads/master", "repository":{"name":"tree-planter", "url":"https://github.com/genebean/tree-planter.git" }}' \
http://localhost:80/deploy

curl -H "Content-Type: application/json" -X POST -d \
'{"ref":"refs/heads/master", "repository":{"name":"tree-planter", "url":"https://github.com/genebean/tree-planter.git" }}' \
http://localhost:80/gitlab

ls -ld /home/vagrant/trees/

ls -l /home/vagrant/trees/
```

Alternatively, you could simply run `vagrant destroy -f; vagrant up` to recreate the Vagrant environment from scratch as that will take care of performing a build in a clean environment and then running some basic tests.

If all of that looks good you should also run `rubocop` against your local copy of the code. You can do that from inside Vagrant like so:

```bash
~ » docker run --rm -it --entrypoint='' -v /vagrant:/vagrant genebean/tree-planter \
/bin/bash -c 'cd /vagrant; bundle exec rake rubocop'
Running RuboCop...
Inspecting 6 files
......

6 files inspected, no offenses detected
Running RuboCop...
Inspecting 6 files
......

6 files inspected, no offenses detected
```

Many errors that are may be returned can be fixed by running a variation of the command above that has `rake rubocop` replaced with `rake rubocop:auto_correct`.

### Don't forget

Lastly, be sure to check the output of the [`/metrics` endpoint](http://localhost:8080/metrics) if you have made any changes to the Prometheus metrics' code.


[debian]: https://hub.docker.com/_/debian/
[dependabot-img]: https://api.dependabot.com/badges/status?host=github&repo=genebean/tree-planter
[dependabot-url]: https://dependabot.com
Expand All @@ -314,6 +409,6 @@ The repository contains a Vagrantfile that will allow you to fire up a CentOS 7
[puppetlabs/docker]: https://forge.puppet.com/puppetlabs/docker
[ruby]: https://hub.docker.com/_/ruby/
[sinatra]: http://www.sinatrarb.com
[travis-ci]: https://travis-ci.org/genebean/tree-planter
[travis-ci]: https://travis-ci.com/genebean/tree-planter
[travis-img-master]: https://img.shields.io/travis/genebean/tree-planter/master.svg
[vs]: https://www.vagrantup.com/docs/share/http.html
29 changes: 26 additions & 3 deletions tree_planter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
require 'json'
require 'logger'
require 'open3'
require 'prometheus/client'
require 'sinatra/base'

# This is my Sinatra app for planting trees
Expand All @@ -11,6 +12,21 @@ class TreePlanter < Sinatra::Base

config_obj = JSON.parse(File.read(Dir.pwd + '/config.json'))

# rubocop:disable Layout/LineLength
prometheus = Prometheus::Client.registry
tree_deploy_counter = Prometheus::Client::Counter.new(
:tree_deploys,
docstring: 'A count of how many times each variation of each tree has been deployed',
labels: %i[
tree_name
branch_name
repo_path
endpoint
]
)
prometheus.register(tree_deploy_counter)
# rubocop:enable Layout/LineLength

get '/' do
"<h1>Tree Planter</h1>
<h2>To use this tool you need to send a post to one of the following:</h2>
Expand Down Expand Up @@ -68,7 +84,7 @@ class TreePlanter < Sinatra::Base
logger.info('')

# rubocop:disable Layout/LineLength
deploy_tree(endpoint, tree_name, branch_name, repo_url, repo_path, config_obj)
deploy_tree(endpoint, tree_name, branch_name, repo_url, repo_path, config_obj, tree_deploy_counter)
# rubocop:enable Layout/LineLength
end

Expand Down Expand Up @@ -110,7 +126,7 @@ class TreePlanter < Sinatra::Base
elsif after.eql?('0000000000000000000000000000000000000000') && checkout_sha.nil? # newer GitLab JSON Payload
delete_branch(endpoint, repo_path, config_obj)
else
deploy_tree(endpoint, tree_name, branch_name, repo_url, repo_path, config_obj)
deploy_tree(endpoint, tree_name, branch_name, repo_url, repo_path, config_obj, tree_deploy_counter)
end
# rubocop:enable Layout/LineLength

Expand Down Expand Up @@ -195,7 +211,7 @@ def delete_branch(endpoint, repo_path, config_obj)
# rubocop:enable Metrics/AbcSize

# rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Layout/LineLength, Metrics/ParameterLists, Metrics/PerceivedComplexity
def deploy_tree(endpoint, tree_name, branch_name, repo_url, repo_path, config_obj)
def deploy_tree(endpoint, tree_name, branch_name, repo_url, repo_path, config_obj, tree_deploy_counter)
# rubocop:enable Layout/LineLength, Metrics/ParameterLists
base = config_obj['base_dir']

Expand Down Expand Up @@ -256,6 +272,13 @@ def deploy_tree(endpoint, tree_name, branch_name, repo_url, repo_path, config_ob
# body body_content
end
end # end Open3

tree_deploy_counter.increment(labels: {
tree_name: tree_name,
branch_name: branch_name,
repo_path: repo_path,
endpoint: endpoint
})
else
status 500
msg = "#{base} cannot be found"
Expand Down

0 comments on commit 8b58e1c

Please sign in to comment.