Skip to content

Commit 4370e0c

Browse files
authored
Initial commit
0 parents  commit 4370e0c

37 files changed

Lines changed: 1384 additions & 0 deletions

.github/CODEOWNERS

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# This is a comment.
2+
# Each line is a file pattern followed by one or more owners.
3+
4+
# These owners will be the default owners for everything in
5+
# the repo. Unless a later match takes precedence,
6+
# @josephmachado will be requested for
7+
# review when someone opens a pull request.
8+
9+
# REPLACE WITH YOUR GITHUB USER ID !!!!
10+
* @josephmachado

.github/workflows/cd.yml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Note: Uncomment to start CD
2+
# name: CD
3+
# on:
4+
# push:
5+
# branches:
6+
# - main
7+
# jobs:
8+
# deploy-to-ec2:
9+
# runs-on: ubuntu-latest
10+
# steps:
11+
# - name: Deploy to server
12+
# uses: easingthemes/ssh-deploy@main
13+
# env:
14+
# SSH_PRIVATE_KEY: ${{ secrets.SERVER_SSH_KEY }}
15+
# REMOTE_HOST: ${{ secrets.REMOTE_HOST }}
16+
# REMOTE_USER: ${{ secrets.REMOTE_USER }}
17+
# SOURCE: "./"
18+
# TARGET: "/home/ubuntu/data_engineering_project_template"

.github/workflows/ci.yml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# Note: Uncomment to start CI
2+
# name: CI
3+
# on: [pull_request]
4+
# jobs:
5+
# run-ci-tests:
6+
# runs-on: ubuntu-latest
7+
# steps:
8+
# - name: checkout repo
9+
# uses: actions/checkout@v2
10+
# - name: Spin up containers
11+
# run: make up
12+
# - name: Run CI test
13+
# run: make ci

.gitignore

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
### Vim ###
2+
[._]*.s[a-w][a-z]
3+
[._]s[a-w][a-z]
4+
*.un~
5+
Session.vim
6+
.netrwhist
7+
*~
8+
9+
### SublimeText ###
10+
# cache files for sublime text
11+
*.tmlanguage.cache
12+
*.tmPreferences.cache
13+
*.stTheme.cache
14+
15+
# workspace files are user-specific
16+
*.sublime-workspace
17+
18+
# project files should be checked into the repository, unless a significant
19+
# proportion of contributors will probably not be using SublimeText
20+
# *.sublime-project
21+
22+
# sftp configuration file
23+
sftp-config.json
24+
25+
# Python
26+
__pycache__
27+
28+
# policy
29+
trust-policy.json
30+
31+
# logs
32+
logs/*
33+
*.log
34+
35+
temp/*
36+
37+
__MACOSX
38+
39+
.dockerignore
40+
41+
*.pem
42+
43+
###### TERRAFORM IGNORE
44+
# Local .terraform directories
45+
**/.terraform/*
46+
47+
# .tfstate files
48+
*.tfstate
49+
*.tfstate.*
50+
51+
# Crash log files
52+
crash.log
53+
crash.*.log
54+
55+
# Exclude all .tfvars files, which are likely to contain sensitive data, such as
56+
# password, private keys, and other secrets. These should not be part of version
57+
# control as they are data points which are potentially sensitive and subject
58+
# to change depending on the environment.
59+
*.tfvars
60+
*.tfvars.json
61+
62+
# Ignore override files as they are usually used to override resources locally and so
63+
# are not checked in
64+
override.tf
65+
override.tf.json
66+
*_override.tf
67+
*_override.tf.json
68+
69+
# Include override files you do wish to add to version control using negated pattern
70+
# !example_override.tf
71+
72+
# Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan
73+
# example: *tfplan*
74+
75+
# Ignore CLI configuration files
76+
.terraformrc
77+
terraform.rc
78+
Footer
79+
80+
dashboard_files/
81+

.tool-versions

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
python 3.11.1

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2022 Start Data Engineering
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

Makefile

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
####################################################################################################################
2+
# Setup containers to run Airflow
3+
4+
docker-spin-up:
5+
docker compose up airflow-init && docker compose up --build -d
6+
7+
perms:
8+
sudo mkdir -p logs plugins temp dags tests migrations data visualization && sudo chmod -R u=rwx,g=rwx,o=rwx logs plugins temp dags tests migrations data visualization
9+
10+
up: perms docker-spin-up
11+
12+
down:
13+
docker compose down --volumes --rmi all
14+
15+
restart: down up
16+
17+
sh:
18+
docker exec -ti webserver bash
19+
20+
####################################################################################################################
21+
# Testing, auto formatting, type checks, & Lint checks
22+
23+
pytest:
24+
docker exec webserver pytest -p no:warnings -v /opt/airflow/tests
25+
26+
format:
27+
docker exec webserver python -m black -S --line-length 79 .
28+
29+
isort:
30+
docker exec webserver isort .
31+
32+
type:
33+
docker exec webserver mypy --ignore-missing-imports /opt/airflow
34+
35+
lint:
36+
docker exec webserver flake8 /opt/airflow/dags
37+
38+
ci: isort format type lint pytest
39+
40+
####################################################################################################################
41+
# Set up cloud infrastructure
42+
43+
tf-init:
44+
terraform -chdir=./terraform init
45+
46+
infra-up:
47+
terraform -chdir=./terraform apply
48+
49+
infra-down:
50+
terraform -chdir=./terraform destroy
51+
52+
infra-config:
53+
terraform -chdir=./terraform output
54+
55+
####################################################################################################################
56+
# Port forwarding to local machine
57+
58+
cloud-metabase:
59+
terraform -chdir=./terraform output -raw private_key > private_key.pem && chmod 600 private_key.pem && ssh -o "IdentitiesOnly yes" -i private_key.pem ubuntu@$$(terraform -chdir=./terraform output -raw ec2_public_dns) -N -f -L 3001:$$(terraform -chdir=./terraform output -raw ec2_public_dns):3000 && open http://localhost:3001 && rm private_key.pem
60+
61+
cloud-airflow:
62+
terraform -chdir=./terraform output -raw private_key > private_key.pem && chmod 600 private_key.pem && ssh -o "IdentitiesOnly yes" -i private_key.pem ubuntu@$$(terraform -chdir=./terraform output -raw ec2_public_dns) -N -f -L 8081:$$(terraform -chdir=./terraform output -raw ec2_public_dns):8080 && open http://localhost:8081 && rm private_key.pem
63+
64+
####################################################################################################################
65+
# Helpers
66+
67+
ssh-ec2:
68+
terraform -chdir=./terraform output -raw private_key > private_key.pem && chmod 600 private_key.pem && ssh -o StrictHostKeyChecking=no -o IdentitiesOnly=yes -i private_key.pem ubuntu@$$(terraform -chdir=./terraform output -raw ec2_public_dns) && rm private_key.pem

README.md

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
2+
* [Data engineering project template](#data-engineering-project-template)
3+
* [Run Data Pipeline](#run-data-pipeline)
4+
* [Run on codespaces](#run-on-codespaces)
5+
* [Run locally](#run-locally)
6+
* [Architecture and services in this template](#architecture-and-services-in-this-template)
7+
* [Using template](#using-template)
8+
* [Writing pipelines](#writing-pipelines)
9+
* [(Optional) Advanced cloud setup](#optional-advanced-cloud-setup)
10+
* [Prerequisites:](#prerequisites)
11+
* [Tear down infra](#tear-down-infra)
12+
13+
14+
# Data engineering project template
15+
16+
Detailed explanation can be found **[`in this post`](https://www.startdataengineering.com/post/data-engineering-projects-with-free-template/)**
17+
18+
## Run Data Pipeline
19+
20+
Code available at **[data_engineering_project_template](https://github.com/josephmachado/data_engineering_project_template/tree/main?tab=readme-ov-file#data-engineering-project-template)** repository.
21+
22+
### Run on codespaces
23+
24+
You can run this data pipeline using GitHub codespaces. Follow the instructions below.
25+
26+
1. Create codespaces by going to the **[data_engineering_project_template](https://github.com/josephmachado/data_engineering_project_template/tree/main?tab=readme-ov-file#data-engineering-project-template)** repository, cloning it(or click `Use this template` button) and then clicking on `Create codespaces on main` button.
27+
2. Wait for codespaces to start, then in the terminal type `make up`.
28+
3. Wait for `make up` to complete, and then wait for 30s (for Airflow to start).
29+
4. After 30s go to the `ports` tab and click on the link exposing port `8080` to access Airflow UI (username and password is `airflow`).
30+
31+
![codespaces start](./assets/images/cs1.png)
32+
![codespaces make up](./assets/images/cs2.png)
33+
![codespaces open url](./assets/images/cs3.png)
34+
35+
### Run locally
36+
37+
To run locally, you need:
38+
39+
1. [git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git)
40+
2. [Github account](https://github.com/)
41+
3. [Docker](https://docs.docker.com/engine/install/) with at least 4GB of RAM and [Docker Compose](https://docs.docker.com/compose/install/) v1.27.0 or later
42+
43+
Clone the repo and run the following commands to start the data pipeline:
44+
45+
```bash
46+
git clone https://github.com/josephmachado/data_engineering_project_template.git
47+
cd data_engineering_project_template
48+
make up
49+
sleep 30 # wait for Airflow to start
50+
make ci # run checks and tests
51+
```
52+
Go to [http:localhost:8080](http:localhost:8080) to see the Airflow UI. Username and password are both `airflow`.
53+
54+
## Architecture and services in this template
55+
56+
This data engineering project template, includes the following:
57+
58+
1. **`Airflow`**: To schedule and orchestrate DAGs.
59+
2. **`Postgres`**: To store Airflow's details (which you can see via Airflow UI) and also has a schema to represent upstream databases.
60+
3. **`DuckDB`**: To act as our warehouse
61+
4. **`Quarto with Plotly`**: To convert code in `markdown` format to html files that can be embedded in your app or servered as is.
62+
5. **`cuallee`**: To run data quality checks on the data we extracted from CoinCap API.
63+
6. **`minio`**: To provide an S3 compatible open source storage system.
64+
65+
For simplicity services 1-5 of the above are installed and run in one container defined [here](./containers/airflow/Dockerfile).
66+
67+
![DET](./assets/images/det2.png)
68+
69+
The `coincap_elt` DAG in the [Airflow UI](http://localhost:8080) will look like the below image:
70+
71+
![DAG](./assets/images/dag.png)
72+
73+
You can see the rendered html at [./visualizations/dashboard.html](https://github.com/josephmachado/data_engineering_project_template/blob/main/visualization/dashboard.html).
74+
75+
The file structure of our repo is as shown below:
76+
77+
![File strucutre](./assets/images/fs.png)
78+
79+
## Using template
80+
81+
You can use this repo as a template and create your own, click on the `Use this template` button.
82+
83+
![Template](./assets/images/template.png)
84+
85+
## Writing pipelines
86+
87+
We have a sample pipeline at [coincap_elt.py](./dags/coincap_elt.py) that you can use as a starter to create your own DAGs. The tests are available at [./tests](./tests) folder.
88+
89+
Once the `coincap_elt` DAG runs, we can see the dashboard html at [./visualization/dashboard.html](./visualization/dashboard.html) and will look like ![Dashboard](./assets/images/dash.png).
90+
91+
## (Optional) Advanced cloud setup
92+
93+
If you want to run your code on an EC2 instance, with terraform, follow the steps below.
94+
95+
### Prerequisites:
96+
97+
1. [Terraform](https://learn.hashicorp.com/tutorials/terraform/install-cli)
98+
2. [AWS account](https://aws.amazon.com/)
99+
3. [AWS CLI installed](https://docs.aws.amazon.com/cli/latest/userguide/install-cliv2.html) and [configured](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-configure.html)
100+
101+
You can create your GitHub repository based on this template by clicking on the `Use this template button in the **[data_engineering_project_template](https://github.com/josephmachado/data_engineering_project_template)** repository. Clone your repository and replace content in the following files
102+
103+
1. **[CODEOWNERS](https://github.com/josephmachado/data_engineering_project_template/blob/main/.github/CODEOWNERS)**: In this file change the user id from `@josephmachado` to your Github user id.
104+
2. **[cd.yml](https://github.com/josephmachado/data_engineering_project_template/blob/main/.github/workflows/cd.yml)**: In this file change the `data_engineering_project_template` part of the `TARGET` parameter to your repository name.
105+
3. **[variable.tf](https://github.com/josephmachado/data_engineering_project_template/blob/main/terraform/variable.tf)**: In this file change the default values for `alert_email_id` and `repo_url` variables with your email and [github repository url](https://www.theserverside.com/blog/Coffee-Talk-Java-News-Stories-and-Opinions/GitHub-URL-find-use-example) respectively.
106+
107+
Run the following commands in your project directory.
108+
109+
```shell
110+
# Create AWS services with Terraform
111+
make tf-init # Only needed on your first terraform run (or if you add new providers)
112+
make infra-up # type in yes after verifying the changes TF will make
113+
114+
# Wait until the EC2 instance is initialized, you can check this via your AWS UI
115+
# See "Status Check" on the EC2 console, it should be "2/2 checks passed" before proceeding
116+
# Wait another 5 mins, Airflow takes a while to start up
117+
118+
make cloud-airflow # this command will forward Airflow port from EC2 to your machine and opens it in the browser
119+
# the user name and password are both airflow
120+
121+
make cloud-metabase # this command will forward Metabase port from EC2 to your machine and opens it in the browser
122+
# use https://github.com/josephmachado/data_engineering_project_template/blob/main/env file to connect to the warehouse from metabase
123+
```
124+
125+
For the [continuous delivery](https://github.com/josephmachado/data_engineering_project_template/blob/main/.github/workflows/cd.yml) to work, set up the infrastructure with terraform, & defined the following repository secrets. You can set up the repository secrets by going to `Settings > Secrets > Actions > New repository secret`.
126+
127+
1. **`SERVER_SSH_KEY`**: We can get this by running `terraform -chdir=./terraform output -raw private_key` in the project directory and paste the entire content in a new Action secret called SERVER_SSH_KEY.
128+
2. **`REMOTE_HOST`**: Get this by running `terraform -chdir=./terraform output -raw ec2_public_dns` in the project directory.
129+
3. **`REMOTE_USER`**: The value for this is **ubuntu**.
130+
131+
### Tear down infra
132+
133+
After you are done, make sure to destroy your cloud infrastructure.
134+
135+
```shell
136+
make down # Stop docker containers on your computer
137+
make infra-down # type in yes after verifying the changes TF will make
138+
```
139+

assets/images/cs1.png

136 KB
Loading

assets/images/cs2.png

114 KB
Loading

0 commit comments

Comments
 (0)