setting up continuous delivery with drone

Long, long time ago, i started to manage my spare time projects with git, to make life a bit easier there were tools like gitosis and later gitolite - you managed repositories and public keys in plain text files and git hooks on the server. Last year i decided to join the shiny new world of modern self-hosting git services. I choose Gitea - copied it on the server, started one 40 mb binary, and it was just working - and it was fast.

Really impressed about the performance and simple deployments, i wanted to learn that sorcery.

Spoiler: The secret is go…

the old way

Similar to the repository management, my continouse delivery “pipeline” was a git hook (created by hand) and a bash script. That was working well enough for code, not delivered as a binary, like octobercms, playframework projects or hugo sites where you only have to check out the code and run something - the server has to be prepared for that of course.

In a scenario where i have a react-based frontend, have to build a javascript bundle and want it to be packed in a go binary, things get a bit more complex. At HORNBACH we usually build our software with Jenkins CI - but i don’t like the limited groovy pipeline syntax - and the jenkins nodes needs a setup by hand.

I searched for something more intuitive.

starting the drone

After a short stop at CircleCI (it’s only working with github) i found!

The quickstart is really quick, ~20 lines of yaml and docker-compose up is everything needed:

version: '2'

    image: drone/drone:0.8

      - 8080:8000
      - 9000
      - ./.drone:/var/lib/drone/
    restart: always
      - DRONE_OPEN=false
      - DRONE_HOST=
      - DRONE_SECRET=123456
      - DRONE_GITEA=true

    image: drone/agent:0.8

    command: agent
    restart: always
      - drone-server
      - /var/run/docker.sock:/var/run/docker.sock
      - DRONE_SERVER=drone-server:9000
      - DRONE_SECRET=123456

You can now login to drone with your gitea account and activate the drone webhook per simple click.


Hint: at first i forgot a field in the gitea config. For working webhooks, make sure your server config, especially the ROOT_URL is set correctly.


Alright, let’s deliver some code!

My pipeline should:

  • test and build a react frontend to a bundle.js
  • take that bundle and embed it in a go binary
  • upload the go binary to a server
  • start the binary

Drone is loooking for a .drone.yml file in the repository root. Everything is pretty straight forward. I love that i can just use every docker image for my build step, no need to manually install nodejs or go or any other environment by hand.

  base: /go
  path: src/

    image: node
      - cd frontend
      - npm install
      - npm test
      - npm run build

    image: cdreier:packr
      - go get
      - packr build

    image:  appleboy/drone-scp
    username: ssh_username
    secrets: [ ssh_key ]
    target: ~/apps/go-project
    source: go-project

    image: appleboy/drone-ssh
    username: ssh_username
    secrets: [ ssh_key ]
    port: 22
      - pkill go-project
      - cd ~/apps/go-project
      - nohup ./go-project -port 3033 > /dev/null &
branches: master

The drone docs are awesome. Everything i need to know has a short description and good examples. And the plugin registry offers everything you need for publishing and deyployments.

In the second step, I use packr to embed static files in the go binary. For a small speed boost, i created a custom docker image with packr preinstalled.

With the secrets (in the 3rd and 4th step), i can place the password or the private key in the drone server, so i don’t have to check in plaintext passwords or something.

Thanks to go and packr, i do not have any requirements to the server. For simplicity, i just run the binary - no need to dockerize one simple binary in that case.

In conclusion: really good CI/CD solution, easy to setup and everything is just working!

Last posts