Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
34 changes: 27 additions & 7 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ name: CI

on:
push:
branches: ["TODO-replace-with-main"]
branches: ["main"]
pull_request:

jobs:
Expand All @@ -29,10 +29,30 @@ jobs:
- name: Install dependencies
run: pip install -r requirements.txt
- name: Lint
run: echo "TODO implement this step"
- name: Format
run: echo "TODO implement this step"
run: ruff check .
- name: Format check
run: ruff format . --check
- name: Test
run: echo "TODO implement this step"
- name: Build image
run: echo "TODO implement this step"
run: API_KEY=test pytest -q
- name: Build Docker image
run: docker build -t barbari-pipeline:${{ github.sha }} .
# The next four steps need the AZURE_CREDENTIALS secret, which GitHub
# withholds on pull_request runs from forks for security. The `if:` guard
# skips them on fork PRs so CI stays green; the central `Grade ACR push`
# workflow on main handles the actual push from base-repo context.
- name: Azure login
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork == false
uses: azure/login@v2
with:
creds: ${{ secrets.AZURE_CREDENTIALS }}

- name: ACR login
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork == false
run: az acr login --name hyfregistry

- name: Push image to ACR
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork == false
run: |
docker tag barbari-pipeline:${{ github.sha }} hyfregistry.azurecr.io/barbari-pipeline:${{ github.sha }}
docker push hyfregistry.azurecr.io/barbari-pipeline:${{ github.sha }}

3 changes: 2 additions & 1 deletion AI_ASSIST.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,12 @@
## The prompt I gave

<!-- Paste the exact prompt you gave to an LLM (ChatGPT, Claude, Copilot, etc.). -->
I used AI to help me fix my pytest issues. The AI suggested ensuring that all required dependencies (pytest and project modules) are installed, fixing missing imports,

TODO: paste your prompt here.

## The code or suggestion it returned

After applying the changes, all tests passed successfully
<!-- Paste the code or key suggestion the LLM returned. -->

```python
Expand Down
7 changes: 5 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,18 @@
# Replace each TODO comment with the correct Dockerfile instruction.

# TODO: set the base image
FROM TODO
FROM python:3.11-slim

WORKDIR /app

# TODO: copy requirements.txt (before source — this keeps the install layer cached)
COPY requirements.txt .

# TODO: install dependencies
RUN pip install --no-cache-dir -r requirements.txt

# TODO: copy source code
COPY . .

# TODO: set the command that runs when the container starts
CMD ["TODO"]
CMD ["python", "-m", "src.pipeline"]
Binary file added assets/acr_push_week5.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
11 changes: 11 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,14 @@
# ruff==
#
# Add your pinned dependencies below:
azure-identity==1.17.1
azure-storage-blob==12.19.1

pandas==2.2.2
numpy==2.0.1
requests==2.32.3
pytest==8.4.2
matplotlib==3.9.2
ruff==0.8.4
pyarrow==18.1.0

32 changes: 29 additions & 3 deletions src/pipeline.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

Replace every `raise NotImplementedError` below with a real implementation.
"""

import os
import logging
from pathlib import Path

Expand All @@ -24,8 +24,22 @@ def get_config() -> dict:

Raise RuntimeError with a clear message if a required variable is missing.
"""
api_key = os.getenv("API_KEY")
output_dir = os.getenv("OUTPUT_DIR", "output")

if not api_key:
raise RuntimeError("ERROR: API_KEY is not set in environment variables")


return {
"api_key": api_key,
"output_dir": output_dir,

}
raise NotImplementedError("Task 5: read API_KEY and OUTPUT_DIR from the environment")

def clean_name(name: str) -> str:
return name.strip()

def fetch_data(api_key: str) -> list[dict]:
"""
Expand All @@ -34,8 +48,12 @@ def fetch_data(api_key: str) -> list[dict]:
Return a list of at least one dict representing a record.
In a real pipeline you would call requests.get(...) here.
"""
raise NotImplementedError("Task 1: return at least one sample record")
logger.info("fetching data")

return [
{"id": 1, "name": "Alice", "value": 100},
{"id": 2, "name": "Bob", "value": 200},
]

def save_results(records: list[dict], output_dir: Path) -> None:
"""
Expand All @@ -44,7 +62,15 @@ def save_results(records: list[dict], output_dir: Path) -> None:
Create output_dir if it does not exist.
Log the number of records written.
"""
raise NotImplementedError("Task 1: write records to output_dir/results.txt")
output_dir.mkdir(parents=True, exist_ok=True)

file_path = output_dir / "results.txt"

with file_path.open("w") as f:
for record in records:
f.write(f"{record}\n")
logger.info(f"saved {len(records)} records to {file_path}")
#raise NotImplementedError("Task 1: write records to output_dir/results.txt")


def run() -> None:
Expand Down
8 changes: 8 additions & 0 deletions tests/test_pipeline.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,14 @@
import pytest

from src.pipeline import fetch_data, get_config, save_results
from src.pipeline import clean_name

def test_clean_name_strips_whitespace():
assert clean_name(" Alice ") == "Alice"


def test_clean_name_handles_empty():
assert clean_name("") == ""


class TestGetConfig:
Expand Down
Loading