From 8ee3c02dad04e299dc4bc4346666fb0e3f967716 Mon Sep 17 00:00:00 2001 From: Kyle Lesinger Date: Fri, 31 Jul 2026 10:47:06 -0500 Subject: [PATCH] docs: overhaul README into a general test-station landing page Reframe from FTE-first to a general test station: balanced tables of the three reusable actions + five dashboards, a repo-layout table, and a per-module docs index. Keep the APPS links and the project board. FTE-specific seed / PI-loop / reset detail is delegated to docs/FTE_SEED.md. --- README.md | 143 +++++++++++++++++++----------------------------------- 1 file changed, 49 insertions(+), 94 deletions(-) diff --git a/README.md b/README.md index 4b49659..06e62d2 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,10 @@ # veda-github-actions -**A test station for VEDA GitHub Actions + Projects-v2 board seeds.** A safe place to iterate on -Actions and board seed data without touching production. First module: the **FTE capacity report** -(team staffing per Program Increment), so we can experiment with **PI changes** and see the report -diff. Intentionally open — it will grow to host other VEDA Actions experiments. +**A test station for reusable VEDA GitHub Actions, Projects-v2 board seeds, and Netlify dashboards.** +One repo where we iterate safely on reusable Actions, their seed/generator tooling, and the SPAs that +render the output — without touching production. It currently ships **three composite actions**, an +**AWS pricing data generator**, and **five dashboards**. Intentionally open — it grows to host new +VEDA Actions experiments. ## 📋 Project board → https://github.com/users/kyle-lesinger/projects/2 @@ -14,102 +15,56 @@ diff. Intentionally open — it will grow to host other VEDA Actions experiments ### 🧭 **DSE Hub:** https://veda-dse-hub.netlify.app ### 💵 **AWS Cost Calculator (Disasters Hub):** https://veda-aws-dashboard.netlify.app -## Use this action in another repo -The report is a **reusable composite action** (`action.yml`). Any repo can import it — just point -it at a Projects v2 board and give it a project-read token. Only **two required inputs**; the repo, -owner, and project number are derived: +## Reusable actions +Each action is a **composite** you import with `uses:`. One repo exposes many via subfolders. -```yaml -# .github/workflows/fte.yml in the consuming repo -jobs: - fte: - runs-on: ubuntu-latest - steps: - - uses: NASA-IMPACT/veda-github-actions@v1 - id: report - with: - project-url: https://github.com/orgs/YOUR-ORG/projects/5 # your board - token: ${{ secrets.PROJECT_TOKEN_FOR_BOARD_READS }} # PAT: repo+read:org+project (or an App token) - # pi: "PI 27.2" # optional — default is all PIs - # report CSVs + summary are now in ${{ steps.report.outputs.report-dir }} (default: reports/) -``` +| Action | Import (`uses:`) | What it does | +|---|---|---| +| **FTE Capacity Report** | `NASA-IMPACT/veda-github-actions@v1` | Reads a board's Objective issues, joins each issue's `## LOE/FTE` table with its PI/date board fields → per-PI CSVs + `fte_summary.md`. | +| **PR Finder** | `NASA-IMPACT/veda-github-actions/pr-finder@v1` | Crawls each Objective's sub-issue tree (5 levels, cross-repo/org) → the PRs that **close** those issues → CSV + Markdown + USWDS HTML. | +| **Leave Tracker** | `NASA-IMPACT/veda-github-actions/leave@v1` | Parses a color-coded leave `.xlsx` (status = cell **fill color**, no text) → `leaves_.{csv,json}` + coverage. No token/network. | -The action reads the board, joins each Objective's `## LOE/FTE` table with its PI/dates, and writes -PI-slugged `fte_allocations_.csv` (+ `by_person`, `by_role`, `fte_summary_.md`; slug = `pi-26.4` or `all-pis`). **Publishing the result is the -caller's choice** — this repo's own [`fte-report.yml`](.github/workflows/fte-report.yml) dogfoods the -action (`uses: ./`) and then publishes to a `fte-report/` branch + opens a living PR. +- **Generators are stdlib-only Python 3.12 + the `gh` CLI** (no pip deps). +- Board-reading actions need a project-read token — `PROJECT_TOKEN_FOR_BOARD_READS` (classic PAT + `repo+read:org+project`, or an App token). The default `GITHUB_TOKEN` **cannot** read Projects v2. +- Inputs and copy-paste workflow snippets live in each module's doc under [`docs/`](docs/). -## What's here -| Path | Role | -|---|---| -| `action.yml` | **the reusable action** (composite): board → report files. Minimal inputs (`project-url`, `token`). | -| `.github/workflows/fte-report.yml` | thin self-consumer of the action (`uses: ./`) that publishes to `fte-report/` (+ artifact + PR) | -| `.github/scripts/generate_fte_report.py` | the generator the action runs (Python **stdlib only**) | -| `seed/` | recreate the demo: sample issues → real issues → board fields → populate | -| `fte-dashboard/` | React SPA (Netlify) — Capacity Matrix + what-if editor | -| `docs/FTE_SEED.md` | data model, board fields, gotchas | -| `pr-finder/` | **2nd reusable action** (`uses: .../pr-finder@v1`): crawl objectives' sub-issue trees (5 levels, cross-org) → closing PRs (CSV + MD + USWDS HTML) | -| `.github/workflows/pr-finder.yml` | self-consumer that publishes the PR report to the `pr-finder/report` branch | -| `pr-dashboard/` | static Netlify site rendering the PR report — [live](https://veda-pr-dashboard.netlify.app) | -| `docs/PR_FINDER.md` | PR Finder data model, seed harness, gotchas | -| `leave/` | **3rd reusable action** (`uses: .../leave@v1`): parse a color-coded leave `.xlsx` (status = cell fill) → `leaves_.{csv,json}` + coverage (stdlib, no token) | -| `.github/workflows/leave-tracker.yml` | self-consumer that publishes the leave report to the `leave-tracker/report` branch | -| `leave-dashboard/` | React SPA (Netlify) — calendar of who's out, person-picker, team-risk heatmap, add-person-via-PR — [live](https://veda-leave-dashboard.netlify.app) | -| `docs/LEAVE_TRACKER.md` | Leave Tracker data model, color map, overrides, gotchas | - -## Quickstart - -**Offline (no board / no network) — runs the generator on synthetic data:** -```bash -python seed/generate_sample_issues.py -python .github/scripts/generate_fte_report.py \ - --issues-json seed/sample_issues.json --out-dir reports --now "$(date -u +%FT%TZ)" -# → reports/fte_allocations_all-pis.csv (+ fte_by_person_all-pis.csv, fte_by_role_all-pis.csv, fte_summary_all-pis.md, fte_manifest.json) -``` +## Dashboards & apps +Each dashboard is its **own Netlify site** ("Pattern B": one site per folder, base directory = that +folder, its own `netlify.toml`). Live links are in [APPS](#apps-) above. -**Against the live board (recreate the seed once):** -```bash -python seed/bootstrap_board.py # create the 6 board fields on projects/2 -gh label create Objective && gh label create poc-loe -python seed/generate_sample_issues.py -python seed/create_issues.py # create the Objective issues in this repo -python seed/setup_project.py # add to board + set PI / Start / End -python seed/setup_board_grouping.py # set Project / Initiative / Team -``` -Then add the token secret and run the Action: -```bash -gh secret set PROJECT_TOKEN_FOR_BOARD_READS --repo NASA-IMPACT/veda-github-actions # classic PAT: repo+read:org+project -gh workflow run fte-report.yml -f pi="All PIs" -``` +| App | Folder | What it shows | +|---|---|---| +| FTE Dashboard | [`fte-dashboard/`](fte-dashboard/) | Capacity matrix + what-if PI editor; fetches report CSVs at runtime. | +| PR Finder Dashboard | [`pr-dashboard/`](pr-dashboard/) | Renders accumulated PR-per-Objective reports with a report picker. | +| Leave Dashboard | [`leave-dashboard/`](leave-dashboard/) | Calendar of who's out, person-picker, team-risk heatmap, add-person-via-PR. | +| DSE Hub | [`dse-hub/`](dse-hub/) | Tabbed hub: meeting tracker (list / calendar / categories, timezone-aware) + PI roadmap; edits stage in a Changes cart → one prefilled PR. | +| AWS Cost Calculator | [`cost-dashboard/`](cost-dashboard/) | EC2/S3/RDS/Lambda cost calculator on live AWS On-Demand prices + CSV export. | -## PI-change test loop (the point of this repo) -1. Change PIs: edit `PIS` in `seed/generate_sample_issues.py` and/or `PI_WINDOWS` in - `.github/scripts/generate_fte_report.py`; or add a PI option on the board + in the workflow's - `pi` dropdown. -2. Re-seed (or edit the board directly) and re-run the Action. -3. Diff the report on `fte-report/` to see the effect. - -## Reset / reseed -```bash -python seed/cleanup_issues.py --delete # remove the demo issues (dry-run without a flag) -``` -Delete/recreate the board in the GitHub UI for a fully clean slate. +## Repo layout +| Path | Role | +|---|---| +| [`action.yml`](action.yml), [`pr-finder/`](pr-finder/), [`leave/`](leave/) | the three reusable composite actions | +| [`.github/scripts/`](.github/scripts/), [`aws-pricing/`](aws-pricing/), [`seed/`](seed/) | generators + seed/bootstrap tooling (stdlib Python) | +| [`.github/workflows/`](.github/workflows/) | self-consumer workflows that run each action/generator and publish to a report branch | +| `*-dashboard/`, [`dse-hub/`](dse-hub/) | the Netlify SPAs above | +| [`docs/`](docs/) | per-module deep-dives | -## Dashboard + Netlify -Static Vite + React SPA. Its build config lives in **`fte-dashboard/netlify.toml`** (base-relative: -build `npm run build`, publish `dist`). Connect a Netlify site to this repo on `main` with -**base directory = `fte-dashboard`**; Netlify reads that folder's `netlify.toml`. Because the repo is -public, the deployed SPA fetches `fte-report/all-pis` at runtime, so new reports appear on reload with -**no redeploy**. Local dev: -```bash -cd fte-dashboard && npm ci && npm run dev -``` +## Per-module docs +- **FTE Capacity Report** — seed, PI-change test loop, reset/reseed, board fields: [`docs/FTE_SEED.md`](docs/FTE_SEED.md) +- **PR Finder** — crawl model, seed harness, gotchas: [`docs/PR_FINDER.md`](docs/PR_FINDER.md) +- **Leave Tracker** — color map, overrides, gotchas: [`docs/LEAVE_TRACKER.md`](docs/LEAVE_TRACKER.md) +- **DSE Hub** — tabs, recurrence, timezone, Changes cart: [`docs/DSE_HUB.md`](docs/DSE_HUB.md) +- **AWS pricing generator** — Price List API pull, weekly review: [`docs/AWS_PRICING.md`](docs/AWS_PRICING.md) +- **Design decisions log**: [`docs/DECISIONS.md`](docs/DECISIONS.md) -**One independent site per dashboard.** This repo is a test station for many Actions, so each -dashboard is its **own** Netlify site: give it its own `/netlify.toml` and connect a new site -with **base directory = that folder**. Keep **no `netlify.toml` at the repo root** — Netlify applies -a root config (and its `base` key) to *every* site connected to the repo, which would hijack the -others into building the wrong app. +## Conventions (non-obvious) +- Generators are **stdlib-only Python 3.12 + `gh` subprocess** — no `requests`, no pip deps. +- **"Objective"** = the issue title contains `"objective"` (case-insensitive). Shared by the actions. +- **One Netlify site per dashboard; no root `netlify.toml`** — a root config (and its `base` key) + applies to *every* site connected to the repo and would hijack the others into building the wrong app. +- Root `.gitignore` has `*.json`, so `git add ` silently skips needed JSON (each dashboard's + `package.json`/`tsconfig*.json`, data JSON) — you must **`git add -f`** them. --- -Ported from `Disasters-Learning-Portal/disasters-aws-conversion` (PR #74). See `docs/FTE_SEED.md`. +Ported from `Disasters-Learning-Portal/disasters-aws-conversion` (PR #74). See [`docs/FTE_SEED.md`](docs/FTE_SEED.md).