Skip to content

Commit 1086bfe

Browse files
vahid-ahmadiclaude
andcommitted
Add GitHub Actions workflow for auto data generation
- Add CLI module (scottish_budget_data/cli.py) for command-line usage - Add GitHub Actions workflow that triggers on push to main - Workflow runs Python pipeline and commits generated CSV files - Prevents infinite loops with [skip ci] in commit message - Update pyproject.toml with CLI entry point Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent f9f644a commit 1086bfe

File tree

3 files changed

+167
-1
lines changed

3 files changed

+167
-1
lines changed
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
name: Generate Dashboard Data
2+
3+
on:
4+
push:
5+
branches: [main]
6+
paths:
7+
- 'src/scottish_budget_data/**'
8+
- 'data_inputs/**'
9+
- '.github/workflows/generate-data.yml'
10+
workflow_dispatch:
11+
12+
jobs:
13+
generate:
14+
runs-on: ubuntu-latest
15+
# Skip if commit was made by this action to prevent infinite loops
16+
if: "!contains(github.event.head_commit.message, '[skip ci]') && !contains(github.event.head_commit.message, 'Auto-generate dashboard data')"
17+
18+
steps:
19+
- name: Checkout
20+
uses: actions/checkout@v4
21+
with:
22+
token: ${{ secrets.GITHUB_TOKEN }}
23+
24+
- name: Install uv
25+
uses: astral-sh/setup-uv@v4
26+
with:
27+
version: "latest"
28+
29+
- name: Set up Python
30+
run: uv python install 3.11
31+
32+
- name: Install dependencies
33+
env:
34+
HUGGING_FACE_TOKEN: ${{ secrets.HUGGING_FACE_TOKEN }}
35+
run: |
36+
uv pip install --system policyengine-uk pandas numpy h5py
37+
38+
- name: Generate dashboard data
39+
env:
40+
HUGGING_FACE_TOKEN: ${{ secrets.HUGGING_FACE_TOKEN }}
41+
PYTHONPATH: ${{ github.workspace }}/src
42+
run: |
43+
cd ${{ github.workspace }}
44+
python -c "from scottish_budget_data import generate_all_data; generate_all_data()"
45+
46+
- name: Check for changes
47+
id: check_changes
48+
run: |
49+
if git diff --quiet public/data/; then
50+
echo "has_changes=false" >> $GITHUB_OUTPUT
51+
else
52+
echo "has_changes=true" >> $GITHUB_OUTPUT
53+
fi
54+
55+
- name: Commit and push changes
56+
if: steps.check_changes.outputs.has_changes == 'true'
57+
run: |
58+
git config --local user.email "github-actions[bot]@users.noreply.github.com"
59+
git config --local user.name "github-actions[bot]"
60+
git add public/data/
61+
git commit -m "Auto-generate dashboard data [skip ci]"
62+
git push

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ dependencies = [
1212
]
1313

1414
[project.scripts]
15-
generate-data = "scottish_budget_data.pipeline:generate_all_data"
15+
scottish-budget-data = "scottish_budget_data.cli:main"
1616

1717
[build-system]
1818
requires = ["setuptools>=61.0"]

src/scottish_budget_data/cli.py

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
"""Command-line interface for Scottish Budget Data generation."""
2+
3+
import argparse
4+
import sys
5+
from pathlib import Path
6+
7+
from scottish_budget_data.pipeline import generate_all_data
8+
from scottish_budget_data.reforms import get_scottish_budget_reforms
9+
10+
11+
def parse_args(args: list[str] = None) -> argparse.Namespace:
12+
"""Parse command-line arguments."""
13+
parser = argparse.ArgumentParser(
14+
prog="scottish-budget-data",
15+
description="Generate data for Scottish Budget dashboard.",
16+
)
17+
18+
parser.add_argument(
19+
"--output-dir",
20+
type=Path,
21+
default=Path("./public/data"),
22+
help="Output directory for CSV files (default: ./public/data)",
23+
)
24+
25+
parser.add_argument(
26+
"--data-dir",
27+
type=Path,
28+
default=Path("./data"),
29+
help="Directory containing input data files (default: ./data)",
30+
)
31+
32+
parser.add_argument(
33+
"--data-inputs-dir",
34+
type=Path,
35+
default=Path("./data_inputs"),
36+
help="Directory containing reference data (default: ./data_inputs)",
37+
)
38+
39+
parser.add_argument(
40+
"--years",
41+
nargs="+",
42+
type=int,
43+
default=[2026, 2027, 2028, 2029, 2030],
44+
help="Years to calculate (default: 2026 2027 2028 2029 2030)",
45+
)
46+
47+
parser.add_argument(
48+
"--list-reforms",
49+
action="store_true",
50+
help="List all available reform IDs and exit",
51+
)
52+
53+
return parser.parse_args(args)
54+
55+
56+
def print_reforms_list() -> None:
57+
"""Print a list of available reforms."""
58+
print("\nAvailable Reforms:")
59+
print("-" * 50)
60+
for reform in get_scottish_budget_reforms():
61+
print(f" {reform.id}: {reform.name}")
62+
print()
63+
64+
65+
def main(args: list[str] = None) -> int:
66+
"""Main entry point for CLI."""
67+
parsed = parse_args(args)
68+
69+
if parsed.list_reforms:
70+
print_reforms_list()
71+
return 0
72+
73+
print("\n" + "=" * 50)
74+
print("Scottish Budget Data Generator")
75+
print("=" * 50)
76+
print(f"Output: {parsed.output_dir}")
77+
print(f"Years: {parsed.years}")
78+
79+
reforms = get_scottish_budget_reforms()
80+
print(f"Reforms: {len(reforms)}")
81+
print()
82+
83+
try:
84+
generate_all_data(
85+
reforms=reforms,
86+
output_dir=parsed.output_dir,
87+
data_dir=parsed.data_dir,
88+
data_inputs_dir=parsed.data_inputs_dir,
89+
years=parsed.years,
90+
)
91+
print("\n" + "=" * 50)
92+
print("Data generation complete!")
93+
print("=" * 50 + "\n")
94+
return 0
95+
except FileNotFoundError as e:
96+
print(f"\nError: {e}")
97+
return 1
98+
except Exception as e:
99+
print(f"\nUnexpected error: {e}")
100+
raise
101+
102+
103+
if __name__ == "__main__":
104+
sys.exit(main())

0 commit comments

Comments
 (0)