Skip to content
Merged
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
3 changes: 3 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# Auto detect text files and perform LF normalization
* text=auto

# Dataset hashes and byte counts must be identical on Windows and Linux.
*.csv text eol=lf

# pbi-tools emits TMDL with source-significant indentation and trailing blanks.
*.tmdl -whitespace
116 changes: 116 additions & 0 deletions .github/workflows/i1-i4-verification.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
name: NBA I1-I4 verification

on:
push:
branches: [main, agent/nba-i1-i4]
pull_request:
workflow_dispatch:

permissions:
contents: read

jobs:
quality-and-real-etl:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.12"
cache: pip
cache-dependency-path: requirements-dev.lock
- name: Install pinned dependencies
run: |
python -m pip install --upgrade pip
python -m pip install -r requirements-dev.lock
python -m pip install --no-deps -e .
- name: Validate generated artifacts and source
run: |
python scripts/generate_model_artifacts.py --check
python -m ruff check src tests scripts/generate_model_artifacts.py scripts/update_powerbi_project_i4.py scripts/validate_i1_i4.py
python scripts/validate_s1_s4.py
python scripts/validate_i1_i4.py
- name: Test core ETL
run: python -m pytest --cov=nba_pipeline --cov-report=term-missing
- name: Process the six real CSV files
run: |
python scripts/normalize_csv_line_endings.py
python -m nba_pipeline transform --input-dir CODE/data_raw --run-dir ci-run --evidence-dir ci-evidence/etl
python -m nba_pipeline validate-model --run-dir ci-run
- uses: actions/upload-artifact@v4
with:
name: nba-real-etl-evidence
path: ci-evidence/etl
if-no-files-found: error

sql-server-integration:
runs-on: ubuntu-latest
services:
sqlserver:
image: mcr.microsoft.com/mssql/server:2022-latest
env:
ACCEPT_EULA: "Y"
MSSQL_SA_PASSWORD: "CI_Strong_Only_2026!"
ports:
- 1433:1433
env:
NBA_SQL_DRIVER: ODBC Driver 18 for SQL Server
NBA_SQL_SERVER: localhost,1433
NBA_SQL_DATABASE: NBA_CI
NBA_SQL_TRUSTED_CONNECTION: "no"
NBA_SQL_USER: sa
NBA_SQL_PASSWORD: "CI_Strong_Only_2026!"
NBA_SQL_ENCRYPT: "no"
NBA_SQL_TRUST_SERVER_CERTIFICATE: "yes"
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.12"
cache: pip
cache-dependency-path: requirements-dev.lock
- name: Install Microsoft ODBC Driver 18
shell: bash
run: |
. /etc/os-release
curl -fsSLo /tmp/packages-microsoft-prod.deb "https://packages.microsoft.com/config/ubuntu/${VERSION_ID}/packages-microsoft-prod.deb"
sudo dpkg -i /tmp/packages-microsoft-prod.deb
sudo apt-get update
sudo env ACCEPT_EULA=Y apt-get install -y msodbcsql18 unixodbc-dev
- name: Install pinned Python dependencies
run: |
python -m pip install --upgrade pip
python -m pip install -r requirements-dev.lock
python -m pip install --no-deps -e .
- name: Wait for SQL Server
shell: bash
run: |
for attempt in {1..30}; do
if python - <<'PY'
import os
import pyodbc
connection = pyodbc.connect(
"DRIVER={ODBC Driver 18 for SQL Server};"
"SERVER=localhost,1433;DATABASE=master;UID=sa;"
f"PWD={os.environ['NBA_SQL_PASSWORD']};Encrypt=no;TrustServerCertificate=yes;",
timeout=3,
)
connection.close()
PY
then
exit 0
fi
sleep 2
done
exit 1
- name: Load and reconcile the real model
run: |
python scripts/normalize_csv_line_endings.py
python -m nba_pipeline transform --input-dir CODE/data_raw --run-dir ci-run
python -m nba_pipeline load-sql --run-dir ci-run --evidence-dir ci-evidence/sql
python -m nba_pipeline validate-model --run-dir ci-run
- uses: actions/upload-artifact@v4
with:
name: nba-sql-reconciliation
path: ci-evidence/sql
if-no-files-found: error
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,19 @@
# Runtime output
*.log
CODE/data_final/
.artifacts/
evidence/**/data/
evidence/NBA-I1-I4/real-run/
tools/

# Python/editor caches
__pycache__/
*.egg-info/
*.py[cod]
.pytest_cache/
.ruff_cache/
.coverage
htmlcov/
.venv/
venv/
.vscode/
Expand Down
1 change: 1 addition & 0 deletions .python-version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
3.12
17 changes: 10 additions & 7 deletions CODE/.env.example
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
# Copy these names into your environment. Do not commit real values.
NBA_SQL_DRIVER=ODBC Driver 17 for SQL Server
NBA_SQL_SERVER=localhost\\SQLEXPRESS
NBA_SQL_DRIVER=ODBC Driver 18 for SQL Server
NBA_SQL_SERVER=localhost,1433
NBA_SQL_DATABASE=NBA_Project

# Recommended for a local Windows SQL Server connection.
NBA_SQL_TRUSTED_CONNECTION=yes
# Docker / SQL authentication (recommended for the reproducible local demo).
NBA_SQL_TRUSTED_CONNECTION=no
NBA_SQL_USER=sa
NBA_SQL_PASSWORD=replace_with_a_local_secret
NBA_SQL_ENCRYPT=no
NBA_SQL_TRUST_SERVER_CERTIFICATE=yes

# Leave these unset when trusted authentication is enabled.
NBA_SQL_USER=
NBA_SQL_PASSWORD=
# Alternative: set NBA_SQL_TRUSTED_CONNECTION=yes and leave user/password unset
# when using a local SQL Server instance with Windows authentication.
Binary file modified CODE/Dashboard - POWERBI/Analisis_NBA_BestTeam.pbit
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
table 'analytics dim_season'
table 'analytics dim_season'

column season_id
dataType: int64
Expand Down Expand Up @@ -40,7 +40,7 @@
mode: directQuery
source =
let
Origen = Sql.Databases("100.74.116.125,1433"),
Origen = Sql.Databases("localhost,1433"),
NBA_Project = Origen{[Name="NBA_Project"]}[Data],
analytics_dim_season = NBA_Project{[Schema="analytics",Item="dim_season"]}[Data]
in
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
table 'analytics vw_bridge_team_season'
table 'analytics vw_bridge_team_season'

column team_id
dataType: int64
Expand All @@ -22,7 +22,7 @@
mode: directQuery
source =
let
Origen = Sql.Databases("100.74.116.125,1433"),
Origen = Sql.Databases("localhost,1433"),
NBA_Project = Origen{[Name="NBA_Project"]}[Data],
analytics_vw_bridge_team_season = NBA_Project{[Schema="analytics",Item="vw_bridge_team_season"]}[Data]
in
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
table 'analytics vw_q10_recent_top'
table 'analytics vw_q10_recent_top'

column team_name
dataType: string
Expand Down Expand Up @@ -48,7 +48,7 @@
mode: directQuery
source =
let
Origen = Sql.Databases("100.74.116.125,1433"),
Origen = Sql.Databases("localhost,1433"),
NBA_Project = Origen{[Name="NBA_Project"]}[Data],
analytics_vw_q10_recent_top = NBA_Project{[Schema="analytics",Item="vw_q10_recent_top"]}[Data],
#"Columnas con nombre cambiado" = Table.RenameColumns(analytics_vw_q10_recent_top,{{"ppg_10y", "Puntos por partido ultimos 10 años"}, {"winrate_10y", "Porcentaje de victorias ultimos 10 años"}})
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
table 'analytics vw_q1_hist_perf'
table 'analytics vw_q1_hist_perf'

column team_name
dataType: string
Expand Down Expand Up @@ -66,7 +66,7 @@
mode: directQuery
source =
let
Origen = Sql.Databases("100.74.116.125,1433"),
Origen = Sql.Databases("localhost,1433"),
NBA_Project = Origen{[Name="NBA_Project"]}[Data],
analytics_vw_q1_hist_perf = NBA_Project{[Schema="analytics",Item="vw_q1_hist_perf"]}[Data]
in
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
table 'analytics vw_q2_age_vs_current'
table 'analytics vw_q2_age_vs_current'

column team_name
dataType: string
Expand Down Expand Up @@ -49,7 +49,7 @@
mode: directQuery
source =
let
Origen = Sql.Databases("100.74.116.125,1433"),
Origen = Sql.Databases("localhost,1433"),
NBA_Project = Origen{[Name="NBA_Project"]}[Data],
analytics_vw_q2_age_vs_current = NBA_Project{[Schema="analytics",Item="vw_q2_age_vs_current"]}[Data]
in
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
table 'analytics vw_q3_player_context_offense'
table 'analytics vw_q3_player_context_offense'

column player_id
dataType: int64
Expand Down Expand Up @@ -48,7 +48,7 @@
mode: directQuery
source =
let
Origen = Sql.Databases("100.74.116.125,1433"),
Origen = Sql.Databases("localhost,1433"),
NBA_Project = Origen{[Name="NBA_Project"]}[Data],
analytics_vw_q3_player_context_offense = NBA_Project{[Schema="analytics",Item="vw_q3_player_context_offense"]}[Data],
#"Columnas con nombre cambiado" = Table.RenameColumns(analytics_vw_q3_player_context_offense,{{"avg_ppg", "Puntos por partido"}, {"avg_fg_pct", "Porcentaje de acierto"}})
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
table 'analytics vw_q4_ppg_by_decade'
table 'analytics vw_q4_ppg_by_decade'

column decade
dataType: int64
Expand All @@ -23,7 +23,7 @@
mode: directQuery
source =
let
Origen = Sql.Databases("100.74.116.125,1433"),
Origen = Sql.Databases("localhost,1433"),
NBA_Project = Origen{[Name="NBA_Project"]}[Data],
analytics_vw_q4_ppg_by_decade = NBA_Project{[Schema="analytics",Item="vw_q4_ppg_by_decade"]}[Data]
in
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
table 'analytics vw_q5_consistency'
table 'analytics vw_q5_consistency'

column team_name
dataType: string
Expand Down Expand Up @@ -31,7 +31,7 @@
mode: directQuery
source =
let
Origen = Sql.Databases("100.74.116.125,1433"),
Origen = Sql.Databases("localhost,1433"),
NBA_Project = Origen{[Name="NBA_Project"]}[Data],
analytics_vw_q5_consistency = NBA_Project{[Schema="analytics",Item="vw_q5_consistency"]}[Data]
in
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
table 'analytics vw_q6_home_away_impact'
table 'analytics vw_q6_home_away_impact'

measure PPG_Diferencia_Home_Away = ```

Expand Down Expand Up @@ -77,7 +77,7 @@
mode: directQuery
source =
let
Origen = Sql.Databases("100.74.116.125,1433"),
Origen = Sql.Databases("localhost,1433"),
NBA_Project = Origen{[Name="NBA_Project"]}[Data],
analytics_vw_q6_home_away_impact = NBA_Project{[Schema="analytics",Item="vw_q6_home_away_impact"]}[Data],
#"Columnas con nombre cambiado" = Table.RenameColumns(analytics_vw_q6_home_away_impact,{{"ppg_home", "Puntos como Local"}, {"ppg_away", "Puntos como visitante"}})
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
table 'analytics vw_q7_balance_of_def'
table 'analytics vw_q7_balance_of_def'

column team_name
dataType: string
Expand Down Expand Up @@ -49,7 +49,7 @@
mode: directQuery
source =
let
Origen = Sql.Databases("100.74.116.125,1433"),
Origen = Sql.Databases("localhost,1433"),
NBA_Project = Origen{[Name="NBA_Project"]}[Data],
analytics_vw_q7_balance_of_def = NBA_Project{[Schema="analytics",Item="vw_q7_balance_of_def"]}[Data],
#"Columnas con nombre cambiado" = Table.RenameColumns(analytics_vw_q7_balance_of_def,{{"fg_pct_avg", "Eficiencia de tiro"}, {"tov_avg", "Balones perdidos"}})
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
table 'analytics vw_q8_longest_win_streak'
table 'analytics vw_q8_longest_win_streak'

column team_name
dataType: string
Expand Down Expand Up @@ -30,7 +30,7 @@
mode: directQuery
source =
let
Origen = Sql.Databases("100.74.116.125,1433"),
Origen = Sql.Databases("localhost,1433"),
NBA_Project = Origen{[Name="NBA_Project"]}[Data],
analytics_vw_q8_longest_win_streak = NBA_Project{[Schema="analytics",Item="vw_q8_longest_win_streak"]}[Data]
in
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
table 'analytics vw_q9_physical_profile'
table 'analytics vw_q9_physical_profile'

column team_name
dataType: string
Expand Down Expand Up @@ -41,7 +41,7 @@
mode: directQuery
source =
let
Origen = Sql.Databases("100.74.116.125,1433"),
Origen = Sql.Databases("localhost,1433"),
NBA_Project = Origen{[Name="NBA_Project"]}[Data],
analytics_vw_q9_physical_profile = NBA_Project{[Schema="analytics",Item="vw_q9_physical_profile"]}[Data]
in
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
table 'analytics vw_team_season_basic'
table 'analytics vw_team_season_basic'

column team_id
dataType: int64
Expand Down Expand Up @@ -31,7 +31,7 @@
mode: directQuery
source =
let
Origen = Sql.Databases("100.74.116.125,1433"),
Origen = Sql.Databases("localhost,1433"),
NBA_Project = Origen{[Name="NBA_Project"]}[Data],
analytics_vw_team_season_basic = NBA_Project{[Schema="analytics",Item="vw_team_season_basic"]}[Data]
in
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
table 'analytics vw_team_season_metrics'
table 'analytics vw_team_season_metrics'

column team_id
dataType: int64
Expand Down Expand Up @@ -79,7 +79,7 @@
mode: directQuery
source =
let
Origen = Sql.Databases("100.74.116.125,1433"),
Origen = Sql.Databases("localhost,1433"),
NBA_Project = Origen{[Name="NBA_Project"]}[Data],
analytics_vw_team_season_metrics = NBA_Project{[Schema="analytics",Item="vw_team_season_metrics"]}[Data]
in
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
table 'analytics vw_teams'
table 'analytics vw_teams'

column team_id
dataType: int64
Expand Down Expand Up @@ -30,7 +30,7 @@
mode: directQuery
source =
let
Origen = Sql.Databases("100.74.116.125,1433"),
Origen = Sql.Databases("localhost,1433"),
NBA_Project = Origen{[Name="NBA_Project"]}[Data],
analytics_vw_teams = NBA_Project{[Schema="analytics",Item="vw_teams"]}[Data]
in
Expand Down
Loading
Loading