Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
237fe40
fix(fk): add new relations in dim_user_storie
JoaoMatheusLamao Apr 28, 2025
4ebd265
refactor(black): apply black formatting
JoaoMatheusLamao Apr 28, 2025
080dbbb
feat(new api) - scrum-108: new api to get all users
JoaoMatheusLamao May 9, 2025
9bee89e
fix(parameter): change parameters
JoaoMatheusLamao May 10, 2025
93c62bc
Merge pull request #12 from QuantumBitBR/fix-scrum-108-new-api-to-get…
santosjhony12 May 10, 2025
31e796e
feat-scrum-127(sprints): insert sprint id in dim_user_story
JoaoMatheusLamao May 21, 2025
4f4a4cd
Merge pull request #13 from QuantumBitBR/feat-scrum-127-insert-sprint
santosjhony12 May 21, 2025
e902975
ci: add ETL workflow
JoaoMatheusLamao May 22, 2025
039c199
feat(rework) - scrum-109: implement logic for calculating "rework" in…
JoaoMatheusLamao May 23, 2025
0907d78
refactor(black) - scrum-109: apply black to all files
JoaoMatheusLamao May 23, 2025
190f9f6
Merge pull request #14 from QuantumBitBR/feat-scrum-109-rework
santosjhony12 May 23, 2025
d4b1dfd
SCRUM-126(chore): ajustando nomenclatura de cada Job
gilvaneamaro May 23, 2025
cea49d0
SCRUM-126(chore): Criando pipeline de testes unitarios
gilvaneamaro May 23, 2025
95f5034
feat-scrum-107(review): some adjustements in logic
JoaoMatheusLamao May 24, 2025
78e3779
Merge pull request #15 from QuantumBitBR/fix-scrum-107-review
santosjhony12 May 24, 2025
daafa24
SCRUM-126(chore): ajustando dependencia dos jobs
gilvaneamaro May 24, 2025
f351681
fix-scrum-107(review): fix tests
JoaoMatheusLamao May 24, 2025
e79df47
Merge branch 'sprint-3' of https://github.com/QuantumBitBR/API_5SEM_E…
JoaoMatheusLamao May 24, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 45 additions & 0 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
name: Continuous Integration - Stratify ETL

on:
push:
branches:
- main
- sprint-3
jobs:
test:
name: Teste unitário
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.x'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
- name: Test with pytest
run: python3 -m unittest discover -s tests

deploy:
name: Deploy
runs-on: ubuntu-latest
needs: test
steps:
- name: Configure SSH
uses: webfactory/ssh-agent@v0.5.3
with:
ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }}

- name: Add Remote Server to Known Hosts
run: |
ssh-keyscan -H ${{ secrets.SERVER_HOST }} >> ~/.ssh/known_hosts

- name: Git Pull on Remote Server
run: |
ssh ${{ secrets.SERVER_USER }}@${{ secrets.SERVER_HOST }} << EOF
cd apps/API_5SEM_ETL/
git pull origin $(git rev-parse --abbrev-ref HEAD)
EOF
79 changes: 60 additions & 19 deletions src/extract/users.py
Original file line number Diff line number Diff line change
@@ -1,25 +1,9 @@
import requests

from src.config import config
from src.utils.logger import Logger


def get_all_users():
"""Returns a list of users from Taiga."""
try:
client = config.TaigaClient()
users = client.api.users.list()

all_users = []

for user in users:
user_complete = client.api.users.get(resource_id=user.id)
all_users.append(user_complete)

return [vars(user) for user in all_users]
except Exception as e:
Logger.error(f"An error occurred while fetching users: {e}")
return []


def get_all_users_by_project(project_id):
"""Returns a list of users by project ID from Taiga."""
try:
Expand All @@ -30,6 +14,15 @@ def get_all_users_by_project(project_id):

for user in users:
user_complete = client.api.users.get(resource_id=user.id)

email = get_useremail_by_project_by_memberships(project_id, user.id)
if email:
user_complete.email = email
else:
Logger.error(
f"Email not found for user {user.id} in project {project_id}."
)

all_users.append(user_complete)

return [vars(user) for user in all_users]
Expand All @@ -38,12 +31,60 @@ def get_all_users_by_project(project_id):
return []


def get_user_by_id(user_id):
def get_user_by_id(user_id, project_id):
"""Returns a user by ID."""
try:
client = config.TaigaClient()
user = client.api.users.get(resource_id=user_id)
email = get_useremail_by_project_by_memberships(project_id, user_id)
if email:
user.email = email
else:
Logger.error(f"Email not found for user {user_id} in project {project_id}.")
return vars(user)
except Exception as e:
Logger.error(f"An error occurred while fetching user {user_id}: {e}")
return None


# In-memory cache for memberships
membership_cache = {}


def get_useremail_by_project_by_memberships(project_id, user_id):
"""Fetches the email of a user by user ID from project memberships in Taiga."""

# Check if the email is already in the cache
if user_id in membership_cache:
return membership_cache[user_id]

token = config.TaigaClient().api.token
if not token:
Logger.error(
"No API token provided. Please set the TAIGA_API_TOKEN environment variable."
)
return None

url = f"https://api.taiga.io/api/v1/memberships?project={project_id}"
headers = {"Authorization": f"Bearer {token}"}

try:
response = requests.get(url, headers=headers)
response.raise_for_status()
memberships = response.json()

for membership in memberships:
user_id_from_membership = membership.get("user")
user_email = membership.get("user_email")
if user_id_from_membership and user_email:
# Populate the cache with the user email
membership_cache[user_id_from_membership] = user_email

if user_id_from_membership == user_id:
return user_email

Logger.error(f"No user with ID {user_id} found in project {project_id}.")
return None
except requests.exceptions.RequestException as e:
Logger.error(f"An error occurred while fetching project memberships: {e}")
return None
14 changes: 7 additions & 7 deletions src/map/fact_eficiencia_user_story.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,23 +59,23 @@ def process_data_2_fact_eficiencia():

created_date = datetime.datetime.strptime(
story["created_date"], "%Y-%m-%dT%H:%M:%S.%fZ"
)
).replace(tzinfo=datetime.timezone.utc)
finish_date = story["finish_date"]
if finish_date is None:
Logger.warning(
f"Finish date is None for story {story['id']}... skipping"
f"Finish date is None for story {story['id']}... using current datetime"
)
continue
finish_date = datetime.datetime.now(datetime.timezone.utc)
else:
finish_date = datetime.datetime.strptime(
finish_date, "%Y-%m-%dT%H:%M:%S.%fZ"
)
).replace(tzinfo=datetime.timezone.utc)

duration = (
finish_date - created_date
).total_seconds() / 60 # Convert duration to minutes
).total_seconds() / 3600 # Convert duration to hours
Logger.info(
f"Story {story['id']} - Created Date: {created_date}, Finish Date: {finish_date}, Duration (minutes): {duration}"
f"Story {story['id']} - Created Date: {created_date}, Finish Date: {finish_date}, Duration (hours): {duration}"
)

assigned_to_extra_info = story.get("assigned_to_extra_info")
Expand All @@ -89,7 +89,7 @@ def process_data_2_fact_eficiencia():
continue

Logger.info(f"Fetching user details for Taiga ID: {taiga_user_id}")
user_complete = get_user_by_id(taiga_user_id)
user_complete = get_user_by_id(taiga_user_id, project["id"])
if user_complete is None:
Logger.error(
f"User {taiga_user_id} not found in Taiga... skipping story {story['id']}"
Expand Down
2 changes: 1 addition & 1 deletion src/map/fact_user_story_temporais.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ def process_data_2_fact_temporais():
continue

Logger.info(f"Fetching user details for Taiga ID: {taiga_user_id}")
user_complete = get_user_by_id(taiga_user_id)
user_complete = get_user_by_id(taiga_user_id, projetc["id"])
if user_complete is None:
Logger.error(
f"User {taiga_user_id} not found in Taiga... skipping story {story['id']}"
Expand Down
2 changes: 1 addition & 1 deletion src/map/relation_project_user.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ def upsert_relation_project_user():
)
continue

user_complete = get_user_by_id(taiga_user_id)
user_complete = get_user_by_id(taiga_user_id, project["id"])
if user_complete is None:
Logger.error(
f"User {taiga_user_id} not found in Taiga... skipping project {project['id']}"
Expand Down
7 changes: 6 additions & 1 deletion src/map/relation_tag_user_story.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,13 @@ def upsert_relation_tag_us():
)

select_id_tag = "SELECT id FROM public.dim_tag WHERE LOWER(nome) = LOWER(%s)"



trucate_table = "TRUNCATE TABLE public.relacionamento_tag_user_story"
conn = db.get_connection()
conn.cursor().execute(trucate_table)
conn.commit()

Logger.info("Database connection established.")
try:
for project in projects:
Expand Down
Loading