Skip to content

Commit

Permalink
feat: support circleci scenario
Browse files Browse the repository at this point in the history
  • Loading branch information
Ivo Bellin Salarin committed Feb 3, 2020
1 parent 6e23460 commit ed8960c
Show file tree
Hide file tree
Showing 14 changed files with 156 additions and 28 deletions.
File renamed without changes.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ cc.html
diff.html
ccguard.db
venv
notes
8 changes: 8 additions & 0 deletions ccguard/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
from ccguard.ccguard import (
SqliteAdapter,
ReferenceAdapter,
configuration,
GitAdapter,
adapter_factory,
)
from ccguard import redis_adapter, ccguard_sync, web_adapter
16 changes: 8 additions & 8 deletions ccguard/ccguard.py
Original file line number Diff line number Diff line change
Expand Up @@ -265,25 +265,25 @@ def adapter_factory(adapter, config):
if adapter == "sqlite":
adapter_class = SqliteAdapter
if adapter == "redis":
from ccguard.redis_adapter import RedisAdapter
from ccguard import redis_adapter

adapter_class = RedisAdapter
adapter_class = redis_adapter.RedisAdapter
if adapter == "web":
from ccguard.web_adapter import WebAdapter
from ccguard import web_adapter

adapter_class = WebAdapter
adapter_class = web_adapter.WebAdapter

if adapter_class:
return adapter_class

if config.get("adapter.class", None) == "redis":
from ccguard.redis_adapter import RedisAdapter
from ccguard import redis_adapter

adapter_class = RedisAdapter
adapter_class = redis_adapter.RedisAdapter
elif config.get("adapter.class", None) == "web":
from ccguard.web_adapter import WebAdapter
from ccguard import web_adapter

adapter_class = WebAdapter
adapter_class = web_adapter.WebAdapter
else:
adapter_class = SqliteAdapter

Expand Down
2 changes: 1 addition & 1 deletion ccguard/ccguard_log.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
import git
import argparse
from ccguard import ccguard
import ccguard
import logging
from xml.etree import ElementTree

Expand Down
44 changes: 40 additions & 4 deletions ccguard/ccguard_server.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import io
import logging
import argparse
import flask
from flask import request, jsonify
from flask import request, jsonify, abort
from pycobertura import Cobertura
from pycobertura.reporters import HtmlReporter, HtmlReporterDelta
from ccguard import ccguard
import ccguard

app = flask.Flask(__name__)
app.config["DEBUG"] = True
Expand Down Expand Up @@ -41,10 +42,25 @@ def api_references_download_data(repository_id, commit_id):
return adapter.retrieve_cc_data(commit_id)


def check_auth():
token = app.config.get("TOKEN", None)
print(token)
if token:
auth = request.headers.get("authorization", None)
if not auth:
return (401, "Authentication required")
if auth != token:
return (403, "Forbidden")


@app.route(
"/api/v1/references/<string:repository_id>/<string:commit_id>/data", methods=["PUT"]
)
def api_upload_reference(repository_id, commit_id):
halt = check_auth()
if halt:
abort(*halt)

config = ccguard.configuration()
adapter_class = ccguard.adapter_factory(None, config)
with adapter_class(repository_id, config) as adapter:
Expand Down Expand Up @@ -83,8 +99,28 @@ def api_generate_diff(repository_id, commit_id1, commit_id2):
return delta.generate()


def main():
app.run()
def parse_args(args=None):
parser = argparse.ArgumentParser(description="ccguard web server")

parser.add_argument(
"--adapter-class",
help="Choose the adapter to use (choices: sqlite or redis)",
dest="adapter",
)
parser.add_argument(
"--token", dest="token", help="the access token for this server"
)
parser.add_argument(
"--port", dest="port", help="the port to listen on", type=int,
)

return parser.parse_args(args)


def main(args=None):
args = parse_args(args)
app.config["TOKEN"] = args.token
app.run(port=args.port)


if __name__ == "__main__":
Expand Down
5 changes: 2 additions & 3 deletions ccguard/ccguard_sync.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
from ccguard import ccguard
from ccguard import redis_adapter
import ccguard
import argparse


def transfer(
commit_id,
repo_folder=".",
source_adapter_class=ccguard.SqliteAdapter,
dest_adapter_class=redis_adapter.RedisAdapter,
dest_adapter_class=ccguard.redis_adapter.RedisAdapter,
):
inner_callable = prepare_inner_callable(commit_id)
config = ccguard.configuration(repo_folder)
Expand Down
4 changes: 2 additions & 2 deletions ccguard/redis_adapter.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import redis

from ccguard.ccguard import ReferenceAdapter
import ccguard
from datetime import datetime


class RedisAdapter(ReferenceAdapter):
class RedisAdapter(ccguard.ReferenceAdapter):
def __init__(self, repository_id, config={}):
self.repository_id = repository_id
host = config.get("redis.host")
Expand Down
9 changes: 9 additions & 0 deletions ccguard/test_ccguard_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,12 @@ def test_put_reference():
)
assert result.status_code == 200
assert result.data.decode("utf-8") == "OK"


def text_parse_args():
args = ccguard_server.parse_args(
["--adapter", "web", "--port", "1234", "--token", "aaaa"]
)
assert args.token == "aaaa"
assert args.port == 1234
assert args.adapter == "web"
4 changes: 2 additions & 2 deletions ccguard/test_ccguard_sync.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import git
from unittest.mock import MagicMock

from . import ccguard
from . import ccguard_sync
import ccguard
from ccguard import ccguard_sync


def mock_adapter_class(commit_id_):
Expand Down
23 changes: 17 additions & 6 deletions ccguard/web_adapter.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
import os
import requests
from ccguard.ccguard import ReferenceAdapter
import ccguard


class WebAdapter(ReferenceAdapter):
class WebAdapter(ccguard.ReferenceAdapter):
def __init__(self, repository_id, config={}):
self.server = config.get("ccguard.server.address")
conf_key = "ccguard.server.address"
token_key = "ccguard.token"
env_server = os.environ.get(conf_key.replace(".", "_"), None)
self.server = env_server if env_server else config.get(conf_key)
token = os.environ.get(token_key.replace(".", "_"), None)
self.token = token if token else config.get(conf_key, None)
super().__init__(repository_id, config)

def get_cc_commits(self) -> frozenset:
Expand All @@ -22,10 +28,15 @@ def retrieve_cc_data(self, commit_id: str) -> bytes:
return r.content.decode("utf-8")

def persist(self, commit_id: str, data: bytes):
headers = {}
if self.token:
headers["Authorization"] = self.token

r = requests.put(
"{server}/api/v1/references/{repository_id}/{commit_id}/data".format(
self, commit_id=commit_id
)
"{p.server}/api/v1/references/{p.repository_id}/{commit_id}/data".format(
p=self, commit_id=commit_id
),
headers=headers,
)

# does not support `dump` yet
41 changes: 41 additions & 0 deletions docs/how to setup ccguard for CI.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# documentation: how to setup ccguard for CI

## launch the server

the aim of the server is to centralize the code coverage data for the whole team, and to ensure that it has not regressed.

on a machine accessible via internet

```sh
pip install ccguard
# for more safety, change the port anc the token
ccguard_server --port 17132 --token EyNHvrWsP6BiiS3QrmzoY3NQNmHLMeYD7SVfAVYK
```

## circleci

expose environment variables

```sh
CCGUARD_SERVER_ADDRESS=http://ccguard_server:17132
CCGUARD_TOKEN=EyNHvrWsP6BiiS3QrmzoY3NQNmHLMeYD7SVfAVYK
```

add to your circleci.yaml

```sh
ccguard --adapter web coverage.xml
```

## on every team member host

you can retrieve the data collected by ccguard, periodically, with the command

```sh
CCGUARD_SERVER_ADDRESS=http://ccguard_server:17132
# no token required to retrieve the coverage data
# retrieve the data (requires ccguard 0.4)
ccguard_sync web sqlite
# inspect the log (directly in the repository you want to check)
ccguard_log
```
4 changes: 2 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

setuptools.setup(
name="ccguard",
version="0.2.1",
version="0.3",
entry_points={
"console_scripts": [
"ccguard=ccguard.ccguard:main",
Expand All @@ -21,7 +21,7 @@
long_description_content_type="text/markdown",
url="https://github.com/nilleb/ccguard",
packages=["ccguard"],
install_requires=["pycobertura", "gitpython", "redis", "flask"],
install_requires=["pycobertura", "gitpython", "redis", "flask", "requests"],
classifiers=[
"Programming Language :: Python :: 3",
"License :: OSI Approved :: GNU Affero General Public License v3 or later (AGPLv3+)",
Expand Down
23 changes: 23 additions & 0 deletions test_distrib.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
rm dist/*.whl
rm -rf /tmp/venv
python3 setup.py bdist_wheel
python3 -m venv /tmp/venv
source /tmp/venv/bin/activate
cd /tmp/
python3 -m pip install /Users/ivo/dev/ccguard/dist/*.whl

#git clone https://github.com/nilleb/fsevents-watcher
#cd fsevents-watcher
exit

# the test scenario follows
source /tmp/venv/bin/activate
ccguard_server --token aaaa --port 8888

source /tmp/venv/bin/activate
export ccguard_server_address=http://localhost:8888
export ccguard_token=aaaa
cd ~/dev/rav1e
ccguard --adapter web coverage.xml
ccguard_log
ccguard_sync

0 comments on commit ed8960c

Please sign in to comment.