Building a CI pipeline with GitHub Actions – Continuous Integration with GitHub Actions and Jenkins-2
This directory contains multiple microservices and is structured as follows:
├── frontend
│ ├── Dockerfile
│ ├── app.py
│ ├── app.test.py
│ ├── requirements.txt
│ ├── static
│ └── templates
├── posts
│ ├── Dockerfile
│ ├── app.py
│ ├── app.test.py
│ └── requirements.txt ├── ratings …
├── reviews …
└── users …
The frontend directory contains files for the frontend microservice, and notably, it includes app.py (the Flask application code), app.test.py (the unit tests for the Flask application), requirements.txt (which contains all Python modules required by the app), and Dockerfile. It also includes a few other directories catering to the user interface elements of this app.
The posts, reviews, ratings, and users microservices have the same structure and contain app.py, app.test.py, requirements.txt, and Dockerfile files.
So, let’s start by switching to the posts directory:
$ cd posts
As we know that Docker is inherently CI-compliant, we can run the tests using Dockerfile itself.
Let’s investigate the Dockerfile of the posts service:
FROM python:3.7-alpine
ENV FLASK_APP=app.py
ENV FLASK_RUN_HOST=0.0.0.0
RUN apk add –no-cache gcc musl-dev linux-headers
COPY requirements.txt requirements.txt
RUN pip install -r requirements.txt
EXPOSE 5000
COPY . .
RUN python app.test.py
CMD [“flask”, “run”]
ThisDockerfile starts with the python:3.7-alpine base image, installs the requirements, and copies the code into the working directory. It runs the app.test.py unit test to check whether the code would work if we deploy it. Finally, the CMD command defines a flask run command to run when we launch the container.
Let’s build our Dockerfile and see what we get:
$ docker build –progress=plain -t posts .
4 [1/6] FROM docker.io/library/python:3.7-alpine
5 [internal] load build context
6 [2/6] RUN apk add — no-cache gcc musl-dev linux-headers
7 [3/6] COPY requirements.txt requirements.txt
8 [4/6] RUN pip install -r requirements.txt
9 [5/6] COPY . .
10 [6/6] RUN python app.test.py
10 0.676 ————————————————-
10 0.676 Ran 8 tests in 0.026s
11 exporting to image
11 naming to docker.io/library/posts done
As we can see, it built the container, executed a test on it, and responded with Ran 8 tests in 0.026s and an OK message. Therefore, we could use Dockerfile to build and test this app. We used the –progress=plain argument with the docker build command. This is because we wanted to see the stepwise output of the logs rather than Docker merging progress into a single message (this is now a default behavior).
Now, let’s look at GitHub Actions and how we can automate this step.