项目作者: vti

项目描述 :
CI server :camel:
高级语言: Perl
项目地址: git://github.com/vti/crafty.git
创建时间: 2017-04-17T21:59:49Z
项目社区:https://github.com/vti/crafty

开源协议:

下载


Crafty

Crafty is a dead simple but useful for personal projects CI server.

Kritika Analysis Status

Screencast1

Features

  • event driven single threaded server
  • dynamic workers (inproc, fork or detach mode)
  • realtime updates
  • realtime log tails
  • REST API
  • integrations with GitHub, GitLab and BitBucket
  • authentication

Demo

Working demo is available at http://crafty.uptosmth.com.

Configuration (YAML)

For default configuration see
data/config.yml.example in this repository.

  1. ---
  2. access:
  3. mode: public
  4. users:
  5. - username: admin
  6. password: ab7762952be439c958a7398492a6a3706117e61a217e0e
  7. hashing: bcrypt
  8. pool:
  9. workers: 2
  10. mode: detach
  11. projects:
  12. - id: app
  13. build:
  14. - sleep 10

Configuration file is validated against Kwalify schema
schema/config.yml.

Authentication

Two modes are available: public and private. The first one public mode means that anonymous users can browse the
crafty server but cannot do any modifying operations like restarting, canceling etc. The private mode will not
accept not logged in users.

Hashing passwords

A special utility util/hash-password.pl is provided to make hashing password easier. For example we want to create
a user admin with password pa$$w0rd using bcrypt hashing algorithm and salt thisismysalt:

  1. $ bin/env util/hash-password.pl --hashing bcrypt --salt thisismysalt admin pa$$w0rd
  2. username: admin
  3. password: 1e52bcc68f3eef5eb9c9a116a678e81dcf7ffa659454dc
  4. hashing: bcrypt
  5. salt: thisismysalt

Put the output into access.users section of the config file.

Installation

Docker

Using existing image

From Docker Hub.

  1. Pull image
  2. $ docker pull vtivti/crafty
  3. Prepare directories
  4. $ mkdir -p crafty/data
  5. $ cd crafty
  6. Prepare config file
  7. $ curl 'https://raw.githubusercontent.com/vti/crafty/master/data/config.yml.example' > data/config.yml
  8. Start container
  9. $ docker run -d --restart always -v $PWD/data/:/opt/crafty/data -p 5000:5000 --name crafty crafty

Build your own image

  1. $ git clone https://github.com/vti/crafty
  2. $ cd crafty
  3. $ sh util/docker-build.sh

From scratch

You have to have Perl :camel: and SQLite3 installed.

  1. Clone
  2. $ git clone https://github.com/vti/crafty
  3. $ cd crafty
  4. Bootstrap
  5. $ bin/bootstrap
  6. or try fast bootstrap (this can be faster, but still experimental)
  7. $ bin/bootstrap-fast
  8. Run migrations (if any)
  9. $ bin/migrate

Starting

  1. $ bin/crafty
  2. $ bin/crafty --listen :8888
  3. $ bin/crafty --config data/config.yml

Integrations

Integrations are possible on both the incoming webhook and outgoing posthook. Examples can be found in
examples directory.

Example GitHub Integration

We are going to integrate incoming webhooks and commit status updates.

  1. Generating personal token

Navigate to https://github.com/settings/tokens and create a personal token with repo:status permission.

  1. Configuring Crafty
  1. ---
  2. projects:
  3. - id: test
  4. webhooks:
  5. - id: github
  6. cgi: github-webhook.sh
  7. build:
  8. - git clone http://github.com/vti/test
  9. post:
  10. - github-create-status.sh

Adjust github-create-status.sh by putting your token inside.

  1. Creating webhook

Create the webhook on GitHub with the following url pattern:

  1. http://crafty.address/webhook/:webhook_id/:project_id

In our case:

  1. http://crafty.address/webhook/github/test
  1. Push to your repository and check the crafty logs.

REST API

Essentials

Authentication

Basic authentication is used. The username and password are loaded from the config:

  1. access:
  2. users:
  3. - username: api
  4. password: ab7762952be439c958a7398492a6a3706117e61a217e0e
  5. hashing: bcrypt

Example:

  1. curl http://api:password@localhost:5000/api/builds

Client Errors

  1. Invalid format

    HTTP/1.1 400 Bad Request

    {“error”:”Invalid JSON”}

  2. Validation errors

    HTTP/1.1 422 Unprocessible Entity

    {“error”:”Invalid fields”,”fields”:{“project”:”Required”}}

Server Errors

  1. Something bad happened

    HTTP/1.1 500 System Error

    {“error”:”Oops”}

Index

  1. GET /api

Response

  1. {
  2. "title": "Crafty REST API",
  3. "documentation": "https://github.com/vti/crafty",
  4. "resources": [{
  5. "method": "GET",
  6. "href": "/",
  7. "rel": "index"
  8. }, ... ]
  9. }

Example

  1. $ curl http://localhost:5000/api

Build Management

List Builds

  1. GET /api/builds

Response

  1. HTTP/1.1 200 Ok
  2. Content-Type: application/json
  3. {
  4. "builds": [{
  5. "status": "S",
  6. "uuid": "d51ef218-2f1b-11e7-ab6d-4dcfdc676234",
  7. "pid": 0,
  8. "is_cancelable": "",
  9. "created": "2017-05-02 11:43:44.430438+0200",
  10. "finished": "2017-05-02 11:43:49.924477+0200",
  11. "status_display": "success",
  12. "is_new": "",
  13. "ref": "refs/heads/master",
  14. "project": "tu",
  15. "is_restartable": "1",
  16. "status_name": "Success",
  17. "duration": 6.48342710037231,
  18. "rev": "123",
  19. "version": 4,
  20. "message": "123",
  21. "author": "vti",
  22. "started": "2017-05-02 11:43:44.558950+0200",
  23. "links": [{
  24. "href": "/api/builds/d51ef218-2f1b-11e7-ab6d-4dcfdc676234",
  25. "rel": "build"
  26. }]
  27. }, ...]
  28. "total": 5,
  29. "pager": {
  30. ...
  31. }
  32. }

Example

  1. $ curl http://localhost:5000/api/builds

Get Build

  1. GET /api/builds/:uuid

Response

  1. HTTP/1.1 200 Ok
  2. Content-Type: application/json
  3. {
  4. "build" :
  5. {
  6. "status": "S",
  7. "uuid": "d51ef218-2f1b-11e7-ab6d-4dcfdc676234",
  8. "pid": 0,
  9. "is_cancelable": "",
  10. "created": "2017-05-02 11:43:44.430438+0200",
  11. "finished": "2017-05-02 11:43:49.924477+0200",
  12. "status_display": "success",
  13. "is_new": "",
  14. "ref": "refs/heads/master",
  15. "project": "tu",
  16. "is_restartable": "1",
  17. "status_name": "Success",
  18. "duration": 6.48342710037231,
  19. "rev": "123",
  20. "version": 4,
  21. "message": "123",
  22. "author": "vti",
  23. "started": "2017-05-02 11:43:44.558950+0200",
  24. "links": [{
  25. "href": "/api/builds/d51ef218-2f1b-11e7-ab6d-4dcfdc676234/log",
  26. "rel": "build_log"
  27. }, ...]
  28. }
  29. }

Example

  1. $ curl http://localhost:5000/api/builds

Create Build

  1. POST /api/builds

Content type

Can be either application/json or application/x-www-form-urlencoded.

Body params

Required

  • project=[string]
  • rev=[string]
  • ref=[string]
  • author=[string]
  • message=[string]

Response

  1. HTTP/1.1 200 Ok
  2. Content-Type: application/json
  3. {"uuid":"d51ef218-2f1b-11e7-ab6d-4dcfdc676234"}

Example

  1. $ curl http://localhost:5000/api/builds -d 'project=tu&rev=123&ref=refs%2fheads%2fmaster&author=vti&message=fix'

Cancel Build

  1. POST /api/builds/:uuid/cancel

Response

  1. HTTP/1.1 200 Ok
  2. Content-Type: application/json
  3. {"ok":1}

Example

  1. $ curl http://localhost:5000/api/builds/d51ef218-2f1b-11e7-ab6d-4dcfdc676234/cancel

Restart Build

  1. POST /api/builds/:uuid/restart

Response

  1. HTTP/1.1 200 Ok
  2. Content-Type: application/json
  3. {"ok":1}

Example

  1. $ curl http://localhost:5000/api/builds/d51ef218-2f1b-11e7-ab6d-4dcfdc676234/restart

Build Logs

Download raw build log

  1. GET /api/builds/:uuid/log

Response

  1. HTTP/1.0 200 OK
  2. Content-Type: text/plain
  3. Content-Disposition: attachment; filename=6b90cf28-2f12-11e7-b73a-e1bddc676234.log
  4. [...]

Example

  1. $ curl http://localhost:5000/api/builds/d51ef218-2f1b-11e7-ab6d-4dcfdc676234/log

Watching the build log

  1. GET /api/builds/:uuid/tail

Content Type

Output is in text/event-stream format. More info at
MDN.

Response

  1. HTTP/1.0 200 OK
  2. Content-Type: text/event-stream; charset=UTF-8
  3. Access-Control-Allow-Methods: GET
  4. Access-Control-Allow-Credentials: true
  5. data: [...]

Example

  1. $ curl http://localhost:5000/api/builds/d51ef218-2f1b-11e7-ab6d-4dcfdc676234/tail

Events

Watching events

  1. GET /api/events

Content Type

Output is in text/event-stream format. More info at
MDN.

Response

  1. HTTP/1.0 200 OK
  2. Content-Type: text/event-stream; charset=UTF-8
  3. Access-Control-Allow-Methods: GET
  4. Access-Control-Allow-Credentials: true
  5. data: [...]

Example

  1. $ curl http://localhost:5000/api/events

Create event

  1. POST /api/events

Response

  1. HTTP/1.0 200 OK
  2. Content-Type: application/json
  3. {"ok":1}

Example

  1. $ curl http://localhost:5000/api/events -H 'Content-Type: application/json' -d '["event", {"data":"here"}]'

Troubleshooting

Try verbose mode

  1. $ bin/crafty --verbose

Bug Reporting

https://github.com/vti/crafty/issues

Copyright (C) 2017, Viacheslav Tykhanovskyi

This program is free software, you can redistribute it and/or modify it under
the terms of the Artistic License version 2.0.

This program is distributed in the hope that it will be useful, but without any
warranty; without even the implied warranty of merchantability or fitness for
a particular purpose.