UP | HOME

Buildbot CI on freeBSD

Table of Contents

1 Buildbot concepts

  • Buildbot is a job scheduling system - e.g. CI/CD.
  • For installation, you need a master and worker.
  • Master and Worker can start on the same machine.
  • A buildbot master can have 1 to N workers distributed across multiple nodes.

1.1 Builders

A builder (represented as BuildFactory) is an action or a group of actions to build a unit of software.

A builder has a list of workers it can use to execute the build.

You can use a Scheduler to schedule a build.

A build can have a source. (source repo)

2 Setup

2.1 As root

$ pkg install git py36-pip py36-pipenv py36-buildbot py36-buildbot-www

2.2 Create user to run buildbot master

$ pw useradd -n buildbot-master -m -w random

2.3 Directory to hold buildbot master config

E.g. /var/www/buildbot-ci/bb-master

2.4 Switch to directory (e.g. bb-master)

Turn on virtualenv

$ pipenv-3.6 shell

2.5 Give ownership of directory to bb-master user

$ chown buildbot-master:buildbot-master /var/www/buildbot-master

2.6 Switch as unprivileged user

$ su -l buildbot-master

2.7 Create master configuration

$ buildbot-3.6 create-master /var/www/buildbot-master

3 Configure Buildbot Master

3.1 Create master.cfg file

The create-master command creates a master.cfg.sample file you can use to start.

Create a copy.

$ cp /var/www/buildbot-master/master.cfg.sample /var/www/buildbot-master/master.cfg

3.2 Edit master.cfg file

Only relevant parts shown for brevity

c['workers'] = [worker.Worker("example-worker", "pass")] # Worker

c['change_source'] = [] # Source control
c['change_source'].append(changes.GitPoller(
      'git://github.com/buildbot/hello-world.git',  # replace with your repo
      workdir='gitpoller-workdir', branch='master',
      pollInterval=300))

# There are different types of schedules. Poll, force, periodic...
c['schedulers'] = []
c['schedulers'].append(schedulers.SingleBranchScheduler(
                          name="all",
                          change_filter=util.ChangeFilter(branch='master'),
                          treeStableTimer=None,
                          builderNames=["personalsite"]))

c['schedulers'].append(schedulers.ForceScheduler(
                          name="force",
                          builderNames=["personalsite"]))


psf = util.BuildFactory() # Build
psf.addStep(steps.ShellCommand(command=["git", "checkout", "--", "."],
workdir="/var/www/site"))
psf.addStep(steps.ShellCommand(command=["git", "pull"], workdir="/var/www/site"))

psf.addStep(steps.ShellCommand(command=["chmod", "-R", "775", "kiranbusi.com"], workdir="/var/www/personal_site"))


c['builders'] = []   # Add buildfactor to builders
c['builders'].append(
  util.BuilderConfig(name="personalsite",
    workernames=["example-worker"],
    factory=psf))

# Password protect buildbot GUI
c['www']['auth'] = util.UserPasswordAuth([('username','changepassword')])

3.3 Reload configuration

$ buildbot reconfig master
# Run Buildbot Master
$ buildbot start master
# view logs
$ cat master/twistd.log

3.4 Go back to root user

4 Run buildbot master

4.1 Manually

As buildbot-master user in virtual env

In buildbot-master directory (e.g. /var/www/buildbot-master)

$ buildbot start

4.2 Automatically 1

To start on system startup

Define location of master directory

$ sysrc buildbot_basedir=/var/buildbot-master

Specify the user the service should run under

$ sysrc buildbot_user=buildbot-master

Start service at system bootup

$ sysrc buildbot_enable=YES

Start buildbot service

$ service buildbot start

4.3 Verify by checking log file

Look at twistd.log in master config directory

5 Setup buildbot worker

Create a folder to hold buildbot worker config

$ mkdir /var/www/buildbot-worker

Install pkgs

$ pkg install py36-buildbot-worker

Create buildbot-worker user

$ pw useradd -n buildbot-worker -m -w random

Give directory permissions for buildbot-worker user

$ chown buildbot-worker:buildbot-worker /var/buildbot-worker

Swith to buildbot-worker user

5.1 Create buildbot-worker

$ buildbot-worker-3.6 create-worker /var/buildbot-worker localhost worker1 'pass'

Make sure information in master.cfg matches

$ pipenv-3.6 shell # Create a virtualenv using pipenv $ pip install buildbot-worker' # Install buildbot-worker $ pip install setuptools-trial # required for `runtests` build #+ENDSRC

# Create the buildbot worker in the bb-worker virtualenv
# Name of worker: worker
# Host: localhost (name of computer where buildbot master is running )
# Username: worker-A
# Password: pass

$ buildbot-worker create-worker worker localhost worker-A pass

Be sure to match bb-master/master/master.cfg workers

'c['workers'] = [worker.Worker("worker-A", "pass")]'

# Start the worker
# In var/www/buildbot-ci/bb-worker virtualenv run:
buildbot-worker start worker
Following twistd.log until startup finished..
The buildbot-worker appears to have (re)started correctly.

6 Run buildbot-worker

6.1 Manually

As buildbot-worker in buildbot-worker config directory

$ buildbot-worker start

6.2 Automatically

Leverage the rc script by using the service utility to manage the service. Else on every reboot you'll notice your build is down

sysrc buildbot_worker_basedir=/var/buildbot-worker
sysrc buildbot_worker_uid=buildbot-worker
sysrc buildbot_worker_gid=buildbot-worker
sysrc buildbot_worker_enable=YES

Start buildbot worker

$ service buildbot-worker start

Check twistd.log in buildbot-worker directory for success/failure/debug

7 Checkpoint

Verify buildbot is running on port 8010 on localhost

curl http://localhost:8010

8 Nginx Setup

Host buildbot behind nginx

Create a conf file (e.g. /usr/local/etc/nginx/sites/buildbot-nginx.conf

server {
    listen          80;
    server_name     domain_name.com;
     include /usr/local/etc/nginx/snippets/letsencrypt.conf;

     # Redirect other HTTP connections to HTTPS
     location / {
             return  301 https://domain_name.com$request_uri;
     }
 }

 # HTTPS
 server {
     listen  443     ssl;
     server_name     domain_name.com;
      ssl_certificate /usr/local/etc/letsencrypt/live/domain_name.com/fullchain.pem;
      ssl_certificate_key /usr/local/etc/letsencrypt/live/domain_name.com/privkey.pem;

      access_log /var/log/nginx/domain_name.com-access.log;
      error_log /var/log/nginx/domain_name.com-error.log;
      error_page   500 502 503 504  /50x.html;

      location = /50x.html {
              root   /usr/local/www/nginx-dist;
      }

      ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
      ssl_session_cache shared:SSL:1m;
      ssl_session_timeout 10m;
      ssl_ciphers HIGH:!aNULL:!MD5;
      ssl_prefer_server_ciphers  on;

      # Use gzip compression
      gzip on;
      gzip_disable "msie6";
      gzip_vary on;
      gzip_proxied any;
      gzip_comp_level 5;
      gzip_buffers 16 8k;
      gzip_http_version 1.0;

      # Set a variable to work around the lack of nested conditionals
      #set $cache_uri $request_uri;

      # you could use / if you use domain based proxy instead of path based proxy
      location / {

              proxy_set_header HOST $host;
              proxy_set_header X-Real-IP $remote_addr;
              proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
              proxy_set_header X-Forwarded-Proto  $scheme;
              proxy_set_header X-Forwarded-Server  $host;
              proxy_set_header X-Forwarded-Host  $host;
              proxy_pass http://127.0.0.1:8010/;
      }
      location /sse/ {
          # proxy buffering will prevent sse to work
          proxy_buffering off;
          proxy_pass http://127.0.0.1:8010/sse/;
      }
      # required for websocket
      location /ws {
          proxy_http_version 1.1;
          proxy_set_header Upgrade $http_upgrade;
          proxy_set_header Connection "upgrade";
          proxy_pass http://127.0.0.1:8010/ws;
          # raise the proxy timeout for the websocket
          proxy_read_timeout 6000s;
      }

 }

9 Test deployment

9.1 Login via GUI and force build a project

10 Security

  • SSL Certs

    Rerun omitting dry run if dry run works

    $ certbot certonly -d domain_name.com --dry-run
    

11 Postgres

12 Postgres OSX

13 [[Postgres in BSD Jail FreeBSD

14 Setup new database FreeBSD

Footnotes: