Compare commits
	
		
			1 Commits
		
	
	
		
			fantasy-te
			...
			drone-ci
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 4c2b3dff18 | 
							
								
								
									
										116
									
								
								blogs/2022/10/17/drone-ci.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										116
									
								
								blogs/2022/10/17/drone-ci.md
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,116 @@ | |||||||
|  | # Drone CI | ||||||
|  | 
 | ||||||
|  | When it comes to automation, [GitLab CI](https://gitlab.com) has been my go-to for running builds, tests and deployments of projects from static websites to 3D open-world games. | ||||||
|  | This has generally been on a self-hosted installation, and often makes use of physical runners. | ||||||
|  | However, I have some gripes: I mostly only use it for the CI, but it comes with an issue tracker and Git hosting solution too - great for some cases, but overkill in so many others. | ||||||
|  | Because it's such a complete solution, GitLab is a bit of a resource hog, and can often run frustratingly slowly. | ||||||
|  | 
 | ||||||
|  | Recently I've been playing with a friend's self-hosted instance of [Drone CI](https://drone.io/) as a lightweight alternative, and I much prefer it. | ||||||
|  | I didn't set up the instance, so that part is out of scope for this post, but in case it's relevant, we're using a self-hosted [Gitea](gitea.io) instance to host the source. | ||||||
|  | You can find out about configuring Drone with Gitea [here](https://docs.drone.io/server/provider/gitea/). | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | ## Yet Another Yaml Config | ||||||
|  | 
 | ||||||
|  | Like GitLab, Drone is configured via a YAML file at the project root, called `.drone.yml`. | ||||||
|  | Drone is configured by creating 'steps' to the pipeline, where GitLab uses 'jobs'. | ||||||
|  | 
 | ||||||
|  | My first project's automation requirements were small - all I needed for a deployment was to copy all the files in a directory on every push to the `main` branch. | ||||||
|  | This means I needed secure access to the host, and the ability to copy files to it. | ||||||
|  | I didn't want to dedicate any permanent resources to such a small project, so opted for the `docker` pipeline option. | ||||||
|  | 
 | ||||||
|  | My pipeline would contain a single `deploy` step which would configure SSH access to the host, and then use it to copy the relevant files from the checked out version of the project. | ||||||
|  | I decided to use `ubuntu` as the Docker image for familiarity and accessibility - there are probably better options. | ||||||
|  | Drone widely supports Docker image registries; I have not used Docker much, but would like to get more experience with it. | ||||||
|  | 
 | ||||||
|  | ```yml | ||||||
|  | kind: pipeline | ||||||
|  | type: docker | ||||||
|  | name: deploy | ||||||
|  | 
 | ||||||
|  | steps: | ||||||
|  | - name: deploy | ||||||
|  |   image: ubuntu | ||||||
|  |   when: | ||||||
|  |     branch: | ||||||
|  |     - main | ||||||
|  | 
 | ||||||
|  |   commands: | ||||||
|  |     - echo hello world | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | ## Secrets | ||||||
|  | 
 | ||||||
|  | A hugely important aspect of automation is ensuring the security of one's pipelines. | ||||||
|  | Automated access between pipelines is a big risk, and should be locked down as much as possible. | ||||||
|  | For passing around secrets such as passwords and SSH keys, Drone has a concept of secrets. | ||||||
|  | I created a private key on my local machine for the runner's access to the remote host, and added a [per-repository secret](https://docs.drone.io/secret/repository/) to contain the value. | ||||||
|  | This is a named string value which can be accessed from within the context of a single pipeline step. | ||||||
|  | 
 | ||||||
|  | I also created secrets to contain values for the remote host address and the user to login as. | ||||||
|  | These are less of a security concern than the private SSH key, but we should obfuscate them anyway. | ||||||
|  | It's also a useful step towards generalising the pipeline for other projects: I can use the same set of commands in multiple CI configurations, and just update the secrets from the project page. | ||||||
|  | 
 | ||||||
|  | This block was placed in the same step definition as above, below the `image:` entry: | ||||||
|  | 
 | ||||||
|  | ``` | ||||||
|  | environment: | ||||||
|  |   HOST: | ||||||
|  |     from_secret: host | ||||||
|  |   USER: | ||||||
|  |     from_secret: user | ||||||
|  |   SSH_KEY: | ||||||
|  |     from_secret: ssh_key | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | ## Connecting | ||||||
|  | 
 | ||||||
|  | To use the SSH key, we need to spin up `ssh-agent` and load our key into it. | ||||||
|  | Since it's passed into the job as an environment variable, this involves first writing it to a file. | ||||||
|  | We also need to disable host key checking (the bit that asks if you're sure you want to connect to a new host) as we're making an automated SSH connection, and therefore won't be there to type 'yes'. | ||||||
|  | 
 | ||||||
|  | ```yml | ||||||
|  | # configure ssh | ||||||
|  | - eval $(ssh-agent -s) | ||||||
|  | - mkdir -p ~/.ssh | ||||||
|  | - echo "$SSH_KEY" > ~/.ssh/id_rsa | ||||||
|  | - chmod 600 ~/.ssh/id_rsa | ||||||
|  | - ssh-add | ||||||
|  | - echo "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | Finally, it's time to run some SSH commands. | ||||||
|  | I had a bit of trouble getting the hang of variable templating here - it took some trial and error to figure out what variables would get expanded and when. | ||||||
|  | Since my `HOST` and `USER` values are defined in secrets, I had to get them from my evironment variables and into a correctly formatted string for the SSH target. | ||||||
|  | As I would be running multiple commands, I also wanted to store this in a variable to keep the SSH commands short in the Drone config. | ||||||
|  | 
 | ||||||
|  | What ended up working for me was this: | ||||||
|  | 
 | ||||||
|  | ```yml | ||||||
|  | # environment variables get expanded (twice?) | ||||||
|  | - host="$${USER}@$${HOST}" | ||||||
|  | # running 'hostname' on the deploy target | ||||||
|  | - ssh $host "hostname" | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | ## Images | ||||||
|  | 
 | ||||||
|  | It's pretty cool to be able to pass a repository through several Docker images through the pipeline. | ||||||
|  | I have my website's Makefile set up to build off my local machine, which is on Arch. | ||||||
|  | It therefore depends on Arch-specific package names. | ||||||
|  | I didn't want to have to hack around my existing build configuration just to build it automatically, but I also found that the deploy steps I'd already written worked best on Ubuntu. | ||||||
|  | 
 | ||||||
|  | For Drone, this is no problem - I can simply specify `image: archlinux` in the build stage, and `image: ubuntu` for the deploy step. | ||||||
|  | My Makefile and local workflow requires no changes at all, but I can still use the more robust deploy steps from Ubuntu. | ||||||
|  | 
 | ||||||
|  | ## Final thoughts | ||||||
|  | 
 | ||||||
|  | I like Drone's minimalist approach to CI. | ||||||
|  | There isn't much in terms of configuration, and the interface is much snappier than Gitlab's. | ||||||
|  | It will take a bit more work to get a full workflow - Gitlab basically has one out the box - but working with more separate components should provide flexibility and resilience in the long run. | ||||||
|  | 
 | ||||||
|  | I'd like to explore some more features, like [templates](https://docs.drone.io/template/yaml/) for steps shared between repositories, and spend more time tuning exactly when pipelines run. | ||||||
|  | I also want to try building some more complex projects, such as those using game engines like Godot, and those targeting multiple target platforms. | ||||||
|  | Those are adventures for another day, though. | ||||||
|  | 
 | ||||||
|  | That's all for now, thanks for reading and see you next time! | ||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user