Skip to content

feat: Add release workflow, contributing guidelines, and enhance READ… #5

feat: Add release workflow, contributing guidelines, and enhance READ…

feat: Add release workflow, contributing guidelines, and enhance READ… #5

name: Mission JSON Validate
on:
push:
paths:
- 'src/**'
- 'schemas/**'
- '.github/workflows/mission-validate.yml'
pull_request:
jobs:
mission-validate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Install deps
run: |
python -m pip install -U pip
python -m pip install -r requirements.txt jsonschema
- name: Run tiny mission and export JSON + perf CSV
run: |
python -m impulse.mission_cli --waypoints examples/waypoints/simple.json --export mission.json --perf-csv perf.csv --hybrid simulate-first
- name: Validate mission.json against schema
run: |
python bin/validate_mission_json.py mission.json
- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: mission-export
path: |
mission.json
perf.csv
perf-aggregate:

Check failure on line 37 in .github/workflows/mission-validate.yml

View workflow run for this annotation

GitHub Actions / .github/workflows/mission-validate.yml

Invalid workflow file

You have an error in your yaml syntax on line 37
needs: mission-validate
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Install deps
run: |
python -m pip install -U pip
python -m pip install -r requirements.txt
- name: Download perf.csv artifact
uses: actions/download-artifact@v4
with:
name: mission-export
path: ./artifacts
- name: Plot perf summary
run: |
python bin/plot_perf_csv.py --csv ./artifacts/perf.csv --out perf_summary.png
- name: Aggregate perf summary JSON
run: |
# Simulate multiple runs if only one CSV is present
cp ./artifacts/perf.csv ./artifacts/perf_run2.csv
python bin/aggregate_perf_csv.py ./artifacts/perf.csv ./artifacts/perf_run2.csv --out perf_aggregate.json
- name: 40 Eridani A UQ + analysis (100 samples)
run: |
python -m src.uq_validation.impulse_uq_runner --samples 100 --seed 123 --out uq_summary.json --jsonl-out uq_records.jsonl --dist-profile data/dist_profile_40eridani.csv
python bin/aggregate_perf_csv.py ./artifacts/perf.csv --out perf_aggregate.json
# Generate plots from notebook logic with plain Python (no execution needed beyond plotting utilities already used)
python - << 'PY'
import json
from pathlib import Path
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
import numpy as np
records = []
if Path('uq_records.jsonl').exists():
for line in Path('uq_records.jsonl').read_text().splitlines():
if line.strip():
records.append(json.loads(line))
energies = [r.get('planned_energy', 0) for r in records]
if energies:
plt.figure(figsize=(6,4))
plt.hist(energies, bins=15, color='#4C78A8', edgecolor='white')
plt.title('Planned Energy Distribution')
plt.xlabel('Energy (J)')
plt.ylabel('Count')
plt.tight_layout()
plt.savefig('40eridani_energy.png', dpi=150)
feas = [1 if r.get('feasible') else 0 for r in records]
if feas:
n = len(feas)
win = max(1, n//10)
roll = np.convolve(feas, np.ones(win)/win, mode='same')
plt.figure(figsize=(6,4))
plt.plot(roll, color='#F58518')
plt.ylim(0,1)
plt.title('Feasible Fraction (rolling)')
plt.xlabel('Sample Index')
plt.ylabel('Feasible Fraction')
plt.tight_layout()
plt.savefig('40eridani_feasibility.png', dpi=150)
PY
- name: Generate extended 40 Eridani plots
run: |
python - << 'PY'
import json
from pathlib import Path
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
import numpy as np
records = []
if Path('uq_records.jsonl').exists():
for line in Path('uq_records.jsonl').read_text().splitlines():
if line.strip():
records.append(json.loads(line))
energies = [r.get('planned_energy', 0) for r in records]
if energies:
plt.figure(figsize=(6,4))
plt.hist(energies, bins=30, color='#4C78A8', edgecolor='white')
plt.title('Planned Energy Distribution (Extended)')
plt.xlabel('Energy (J)')
plt.ylabel('Count')
plt.tight_layout()
plt.savefig('40eridani_energy_extended.png', dpi=150)
feas = [1 if r.get('feasible') else 0 for r in records]
if feas:
n = len(feas)
win = max(1, n//5)
roll = np.convolve(feas, np.ones(win)/win, mode='same')
plt.figure(figsize=(6,4))
plt.plot(roll, color='#F58518')
plt.ylim(0,1)
plt.title('Feasible Fraction (rolling, Extended)')
plt.xlabel('Sample Index')
plt.ylabel('Feasible Fraction')
plt.tight_layout()
plt.savefig('40eridani_feasibility_extended.png', dpi=150)
PY
- name: Upload perf summary
uses: actions/upload-artifact@v4
with:
name: perf-summary
path: perf_summary.png
- name: Upload 40 Eridani artifacts
uses: actions/upload-artifact@v4
with:
name: 40eridani-artifacts
path: |
uq_summary.json
uq_records.jsonl
perf_aggregate.json
40eridani_energy.png
40eridani_feasibility.png
40eridani_energy_extended.png
40eridani_feasibility_extended.png
- name: Comment summary on PR
if: github.event_name == 'pull_request'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
echo "Posting PR summary..."
ENERGY=$(jq -r '.segment_energy_mean' perf_aggregate.json)
TIME=$(jq -r '.segment_time_mean' perf_aggregate.json)
FEAS=$(jq -r '.feasible_fraction // empty' uq_summary.json 2>/dev/null || echo "")
BODY="Perf Aggregate Summary:%0A- Mean Segment Energy: ${ENERGY} J%0A- Mean Segment Time: ${TIME} s%0A- Feasible Fraction (UQ): ${FEAS}"
gh pr comment ${{ github.event.pull_request.number }} --body "$BODY"