-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Move to tezedge-ci-builder repo * Fix typo
- Loading branch information
Showing
16 changed files
with
508 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,235 @@ | ||
# Tezegde CI - Drone - Continuous Integration platform | ||
|
||
Our CI of choice was [drone](https://www.drone.io/). The following readme was designed to apply to Ubuntu 18.04 and above. | ||
|
||
## Prerequisites | ||
|
||
- Be able to ssh into the desired target hosts with public key authentication with the **SAME** username and public key used on all the hosts | ||
- For the real time runner, we restrict the hardware for a one of hetzner dedicated servers, specifically to [PX-93](https://www.hetzner.com/dedicated-rootserver/px93?country=by) to be able to install our custom compiled kernel with PREEMTP_RT patch | ||
|
||
## Deploying a drone ci for tezedge repository | ||
|
||
### 1. Creating an OAuth Application on github | ||
- GitHub's documentation has a [step by step guide](https://docs.github.com/en/developers/apps/building-oauth-apps/creating-an-oauth-app) | ||
|
||
- The most important is to set the: | ||
- `Application name`: A descriptive name of the Application (E.g.: Tezege Fork CI) | ||
- `Homepage URL`: The url of the `drone_server` with an empty path component (E.g.: http://ci.tezedgem.com) | ||
- `Authorization callback URL`: The url of the `drone_server` with a `login` path component (E.g.: http://ci.tezedgem.com/login) | ||
|
||
- After we have created the OAuth app, we will be redirected to the configuration page. | ||
|
||
- Create a client secret and copy it. Be careful! You can only see the secret once. | ||
|
||
- Copy out the client id. | ||
|
||
The whole process is captured on the following gif: | ||
|
||
![alt text](images/github_oauth_app.gif) | ||
|
||
### 2. Create a shared secret | ||
|
||
The shared secret is used to authenticate communication between runners and our `drone_server`. | ||
|
||
- To create a shared secret, run the following command in a terminal | ||
``` | ||
$ openssl rand -hex 16 | ||
bea26a2221fd8090ea38720fc445eca6 | ||
``` | ||
|
||
### 3. Install ansible | ||
|
||
For comfortable automation, we have created ansible playbooks to deploy a drone ci setup with just a few commands | ||
|
||
``` | ||
$ sudo apt update | ||
$ sudo apt install software-properties-common | ||
$ sudo add-apt-repository --yes --update ppa:ansible/ansible | ||
$ sudo apt install ansible | ||
``` | ||
|
||
### 4. Fork the tezedge repository. | ||
|
||
Fork is important if we want to run our own CI environment as the drone CI runs builds via github webhooks. | ||
|
||
![alt text](images/github_repo_forking.gif) | ||
|
||
### 5. Clone the two repositories | ||
|
||
You will need this repository to set up the CI environment and the forked tezedge repository to execute new builds inside the CI | ||
|
||
``` | ||
$ git clone https://github.com/tezedge/tezedge-ci-builder.git | ||
$ git clone https://github.com/tezedgeUser/tezedge.git | ||
``` | ||
|
||
Please, change the username `tezedgeUser` for the username you forked the repository with. | ||
|
||
### 6. Edit variables and hosts | ||
|
||
Now change directory into the tezedge-ci-builder | ||
|
||
``` | ||
$ cd tezedge-ci-builder/drone_ci_deployment | ||
``` | ||
|
||
Before we run the playbooks, we need to set a few variables that are used in the configuration. In the vars directory, we need to | ||
edit the [variables.yml](vars/variables.yml) | ||
|
||
There are 6 variables we need to set before continuing | ||
|
||
``` | ||
drone_server: The ip/hostname of the machine we wish to set as a server | ||
# User with the ssh connects to the target machines | ||
target_hosts_user: The username with sudo permissions on the target hosts | ||
# The github username you wish to add as an admin for the drone CI | ||
admin_user: The github username of the desired administrator | ||
# Variables for drone server configuration | ||
github_client_id: The client id of the OAuth app | ||
github_client_secret: The client secret of the OAuth app | ||
rpc_secret: The generated shared secret for RPC communication | ||
``` | ||
|
||
Example of a fully edited variables.yml file: | ||
|
||
``` | ||
--- | ||
# The drone server | ||
drone_server: 65.21.165.82 | ||
# User with the ssh connects to the target machines | ||
target_hosts_user: dev | ||
# The github username you wish to add as an admin for the drone CI | ||
admin_user: tezedgeUser | ||
# Variables for drone server configuration | ||
github_client_id: a3e1b143f5cf193c3ef2 | ||
github_client_secret: a4421f712e07eca2ea0fd3f78934a5a5351f3a5e | ||
rpc_secret: 96cac97a56ebe9419709cbffc0849292 | ||
# ** DO NOT EDIT THE VARIABLES BELOW THIS LINE ** | ||
# Path to the tezedge-ci data that needs to be acquired before running the ci | ||
ci_data_path: "/home/{{ target_hosts_user }}" | ||
# SSH configuration | ||
ssh_strict_host_keys: 'no' | ||
ssh_config_file: "/home/{{ target_hosts_user }}/.ssh/config" | ||
... | ||
``` | ||
|
||
The next file we should edit is the [hosts](inventory/hosts) file. This file is in ini format and contains all the hosts we wish to connect to. | ||
|
||
Example of a fully edit host file: | ||
``` | ||
[drone_server] | ||
65.21.165.82 | ||
[drone_runners] | ||
65.21.165.82 | ||
65.21.165.83 | ||
[real_time_runners] | ||
65.21.165.84 | ||
``` | ||
|
||
You can add as many *drone_runners* or *real_time_runners* as we wish. Please be aware of the *real_time_runners* hardware prerequisites talked about earlier in this readme. Note that the `drone_server` can also run a drone_runner | ||
|
||
### 7. Run the ansible playbooks | ||
|
||
**Please keep in mind that we have to run these playbooks in this exact order** | ||
|
||
Once all the variables and hosts are set we can proceed to execute the ansible playbooks. Please double check that we can connect to the target hosts with public key authentication. | ||
|
||
We use the `ansible-playbook` command to execute the playbooks. Here we provide a description for an example `ansible-playbook` command. Use the same user as the `target_hosts_user` we set in the variables.yml. | ||
``` | ||
$ ansible-playbook ./playbooks/docker_setup.yml --user dev --ask-become-pass -i ./inventory/hosts | ||
| | | | | ||
| | | -------> inventory file | ||
| | -------> sudo password for the user | ||
| -------> the user we want to connect to the host | ||
-------> the specific playbook we are running | ||
``` | ||
|
||
After we run the command, ansible will ask for the `BECOME` password. You must enter the user's password, so ansible can execute sudo commands on the host. | ||
|
||
- The first one we run is [docker_setup](playbooks/docker_setup.yml). This playbook prepares the hosts for the docker containers that drone runs in. It installs all the prerequisite packages for docker and docker itself. | ||
|
||
``` | ||
$ ansible-playbook ./playbooks/docker_setup.yml --user dev --ask-become-pass -i ./inventory/hosts | ||
``` | ||
|
||
- As the next step, we run the [real_time_node_setup](playbooks/real_time_node_setup.yml). This playbook downloads and installs the required kernel for the real time environment. It ends in the reboot of the target host. Ansible will wait for the host to come online again. Again, please be aware of the *real_time_runners* hardware prerequisites talked about earlier in this readme. | ||
|
||
``` | ||
$ ansible-playbook ./playbooks/real_time_node_setup.yml --user dev --ask-become-pass -i ./inventory/hosts | ||
``` | ||
|
||
- The next one to run is the [drone_server_setup](playbooks/drone_server_setup.yml). With this we set up and start the drone server. | ||
|
||
``` | ||
$ ansible-playbook ./playbooks/drone_server_setup.yml --user dev --ask-become-pass -i ./inventory/hosts | ||
``` | ||
|
||
- As the final touch, we set up and run all the drone runners. These playbooks will also download all the data needed to run all of our tests in the CI. | ||
|
||
``` | ||
$ ansible-playbook ./playbooks/normal_drone_runner_setup.yml --user dev --ask-become-pass -i ./inventory/hosts | ||
$ ansible-playbook ./playbooks/real_time_drone_runner_setup.yml --user dev --ask-become-pass -i ./inventory/hosts | ||
``` | ||
Please note that both playbooks will stay on `Download data` task quite a long time as they are downloading approximately 29 GB of data for each host. | ||
|
||
### 8. Enable and setup the tezedge repository | ||
|
||
After we ran all the playbooks above we can navigate to the `drone_server` url to enable the repository | ||
|
||
Follow this gif to set up the CI: | ||
|
||
![alt text](images/drone_ui_config.gif) | ||
|
||
With these few steps we enable the repository to send webhooks to our `drone_server`. We also enable the `Trusted` setting and set the pipeline timeouts to 4 hours. | ||
|
||
### 8. Add the drone runner ips/hosts to the synchronize_ci.sh script | ||
|
||
The CI environment is now properly set up! Now all we have to do is to edit the `synchronize_ci.sh`. | ||
|
||
Change directory into tezedge | ||
|
||
``` | ||
$ cd ../tezedge | ||
``` | ||
|
||
This script handles the distribution of the build data across all the runners and can be found in the root of the repository [here](../synchronize_ci.sh) . We need to edit the `CI_HOSTS` array in the script to have all the `drone_runners` and `real_time_runners` included. | ||
|
||
## Run a build | ||
|
||
Done! We now have a fully configured drone CI with all the data required to run the test pipelines. | ||
|
||
To run a build: | ||
|
||
- Create a custom branch | ||
``` | ||
$ git checkout -b ci/testing | ||
``` | ||
|
||
- Commit all of the changes | ||
``` | ||
$ git add . && git commit -m "Our new CI setup" | ||
``` | ||
|
||
- Push the changes to the remote forked github repository | ||
|
||
``` | ||
$ git push origin ci/testing | ||
``` | ||
|
||
Now all we have to do is to create a pull request to the develop branch. After the pull request creation, we will notice a new build in our `drone_server` webpage. |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
[drone_server] | ||
<edit> | ||
|
||
[drone_runners] | ||
<edit> | ||
|
||
[real_time_runners] | ||
<edit> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
- hosts: "*" | ||
become: yes | ||
vars_files: | ||
- ../vars/variables.yml | ||
|
||
tasks: | ||
- name: Install aptitude using apt | ||
apt: name=aptitude state=latest update_cache=yes force_apt_get=yes | ||
|
||
- name: Install required system packages | ||
apt: name={{ item }} state=latest update_cache=yes | ||
loop: [ 'apt-transport-https', 'ca-certificates', 'curl', 'software-properties-common', 'python3-pip', 'virtualenv', 'python3-setuptools'] | ||
|
||
- name: Add Docker GPG apt Key | ||
apt_key: | ||
url: https://download.docker.com/linux/ubuntu/gpg | ||
state: present | ||
|
||
- name: Add Docker Repository | ||
apt_repository: | ||
repo: deb https://download.docker.com/linux/ubuntu bionic stable | ||
state: present | ||
|
||
- name: Update apt and install docker-ce | ||
apt: update_cache=yes name=docker-ce state=latest | ||
|
||
- name: Install Docker Module for Python | ||
pip: | ||
name: docker | ||
|
||
- name: Add user to docker group | ||
user: | ||
name: "{{ target_hosts_user }}" | ||
shell: /bin/bash | ||
groups: docker | ||
append: yes | ||
|
||
- name: Deploy {{ ssh_config_file }} | ||
template: | ||
src : ../templates/ssh_config.j2 | ||
dest : "{{ ssh_config_file }}" | ||
owner : root | ||
group : root | ||
mode : 0600 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
- hosts: "drone_server" | ||
become: yes | ||
vars_files: | ||
- ../vars/variables.yml | ||
tasks: | ||
|
||
- name: Pull drone server image | ||
docker_image: | ||
name: "drone/drone:2" | ||
source: pull | ||
|
||
- name: Deploy environment file | ||
template: | ||
src: ../templates/ci.env.j2 | ||
dest: /home/dev/ci.env | ||
|
||
- name: Deploy starting script | ||
template: | ||
src: ../templates/drone_server.sh.j2 | ||
dest: /home/dev/drone_server.sh | ||
mode : 0755 | ||
|
||
- name: Start the drone server | ||
command: | ||
cmd: '/bin/bash /home/dev/drone_server.sh' |
61 changes: 61 additions & 0 deletions
61
drone_ci_deployment/playbooks/normal_drone_runner_setup.yml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
- hosts: "drone_runners" | ||
# become: yes | ||
vars_files: | ||
- ../vars/variables.yml | ||
tasks: | ||
|
||
- name: Pull drone runner image | ||
docker_image: | ||
name: "drone/drone-runner-docker:1" | ||
source: pull | ||
|
||
- name: Deploy environment file | ||
template: | ||
src: ../templates/ci.env.j2 | ||
dest: "/home/{{ target_hosts_user }}/ci.env" | ||
|
||
- name: Deploy starting script | ||
template: | ||
src: ../templates/drone_runner.sh.j2 | ||
dest: /home/{{ target_hosts_user }}/drone_runner.sh | ||
mode : 0755 | ||
|
||
- name: Download data | ||
shell: "wget -q -m -np -nH -R 'index.html*' http://65.21.165.81:8080/tezedge-ci/ -P {{ ci_data_path }}" | ||
|
||
- name: Move data to the desired location | ||
become: yes | ||
command: mv {{ ci_data_path }}/tezedge-ci /usr/local/etc/tezedge-ci | ||
|
||
- name: SSH KeyGen command | ||
shell: > | ||
ssh-keygen -q -b 2048 -t rsa -N "" -C "creating SSH" -f ~/.ssh/id_rsa | ||
creates="~/.ssh/id_rsa" | ||
- name: Fetch the keyfile from the node to master | ||
fetch: | ||
src: "~/.ssh/id_rsa.pub" | ||
dest: "buffer/{{ inventory_hostname }}-id_rsa.pub" | ||
flat: yes | ||
|
||
- name: Copy the key add to authorized_keys using Ansible module | ||
become: yes | ||
authorized_key: | ||
user: "{{ target_hosts_user }}" | ||
state: present | ||
key: "{{ lookup('file','buffer/{{item}}-id_rsa.pub')}}" | ||
when: "{{ item != inventory_hostname }}" | ||
with_items: | ||
- "{{ groups['drone_runners'] }}" | ||
|
||
- name: Copy id to tezedge-ci dir | ||
command: cp ~/.ssh/id_rsa /usr/local/etc/tezedge-ci/id/id_rsa | ||
|
||
- name: Change outpu-filter permissons | ||
file: | ||
path: /usr/local/etc/tezedge-ci/tools/output-filter | ||
mode: "0775" | ||
|
||
- name: Start the drone runner | ||
command: | ||
cmd: '/bin/bash /home/{{ target_hosts_user }}/drone_runner.sh' |
Oops, something went wrong.