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
51 changes: 51 additions & 0 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# Copilot Instructions for `github-agentic-workflows`

## Big picture architecture
- This is a **2-part app**: Flask API in `backend/` and React (Vite) UI in `frontend/`.
- UI talks to API via relative `/api/*` calls (see `frontend/src/App.jsx`).
- Vite dev server proxies `/api` to `http://localhost:5000` (see `frontend/vite.config.js`), so frontend code should not hardcode backend hostnames.
- Backend state is currently **in-memory** (`items`, `next_id` in `backend/app.py`), so data resets on server restart.

## Service boundaries and data flow
- API routes are in `backend/app.py`:
- `GET /api/health`
- `GET /api/items`
- `POST /api/items` with body `{ "name": string }`
- `DELETE /api/items/<id>`
- Frontend behavior in `frontend/src/App.jsx` mirrors these endpoints:
- initial load -> `fetch('/api/items')`
- add -> `POST /api/items`
- delete -> `DELETE /api/items/:id`
- Keep request/response shapes aligned across both layers when changing endpoints.

## Critical workflows (local)
- Backend setup/run:
- `cd backend && pip install -r requirements.txt`
- `python app.py`
- Frontend setup/run:
- `cd frontend && npm install`
- `npm run dev`
- Frontend quality gates:
- `npm run lint`
- `npm run build`
- `npm test`
- Backend tests:
- `cd backend && python -m pytest test_app.py -v`

## CI/CD behavior to respect
- GitHub Actions build job in `.github/workflows/build-deploy.yml` runs from `frontend/` using Node 20.
- CI currently installs with `npm ci` and runs `npm run build` (not frontend lint/test, and not backend tests).
- If you add required checks, ensure workflow updates stay consistent with existing `frontend/` working-directory assumptions.

## Project-specific patterns
- Frontend tests mock `global.fetch` directly (`frontend/src/test/App.test.jsx`) and use Testing Library + Vitest.
- Test environment is configured in `frontend/vite.config.js` with `jsdom` and `frontend/src/test/setup.js`.
- Flask tests reset mutable module globals before each test (`reset_items` fixture in `backend/test_app.py`). Preserve this pattern when adding backend tests around global state.

## Integration and change guidance
- For API changes, update **all three** together:
1) `backend/app.py` routes/validation,
2) `frontend/src/App.jsx` fetch calls/UI handling,
3) tests in `backend/test_app.py` and/or `frontend/src/test/App.test.jsx`.
- Prefer small, vertical changes (API + UI + tests) over partial edits to avoid broken contract states.
- Keep paths and folder naming as-is (`backend/`, `frontend/`); root `README.md` documents this layout and should be updated if commands/structure change.
6 changes: 3 additions & 3 deletions .github/workflows/build-deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:
# 1. Set working directory for all steps in this job
defaults:
run:
working-directory: src/ui
working-directory: frontend

steps:
- name: Checkout repository
Expand All @@ -26,7 +26,7 @@ jobs:
with:
node-version: '20'
cache: 'npm'
cache-dependency-path: src/ui/package-lock.json # 2. Cache specific to subdir
cache-dependency-path: frontend/package-lock.json # 2. Cache specific to subdir

- name: Install dependencies
run: npm ci
Expand All @@ -38,4 +38,4 @@ jobs:
- name: Upload Build Artifact
uses: actions/upload-pages-artifact@v3
with:
path: 'src/ui/dist'
path: 'frontend/dist'
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@ __pycache__/
*.py[codz]
*$py.class

# Node / frontend
node_modules/
frontend/dist/
frontend/dist-ssr/

# C extensions
*.so

Expand Down
25 changes: 22 additions & 3 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,22 +17,38 @@ Suggested branch naming:
- `docs/<short-description>`

### 2) Install dependencies
This repo currently includes a UI app in `src/ui` (Vite + React).
This repo includes both a frontend and a backend:
- `frontend/` — Vite + React UI
- `backend/` — Flask API

```bash
cd src/ui
cd frontend
npm install

cd ../backend
pip install -r requirements.txt
```

### 3) Run locally
```bash
cd frontend
npm run dev

cd ../backend
python app.py
```

The frontend runs on `http://localhost:5173` and proxies `/api` requests to the backend on `http://localhost:5000`.

### 4) Check quality before opening a PR
```bash
cd frontend
npm run lint
npm run build
npm test

cd ../backend
python -m pytest test_app.py -v
```

If a command fails, include notes in your PR about what failed and why.
Expand All @@ -43,6 +59,7 @@ Good first contributions include:
- Fixing bugs
- Improving docs
- Small UX improvements
- API improvements in the Flask backend
- Refactors that improve readability without changing behavior

For larger changes, please open an issue first to align on scope.
Expand All @@ -53,9 +70,10 @@ Before submitting your PR, make sure:

- [ ] My branch is up to date with `main`
- [ ] I kept the change focused and minimal
- [ ] I ran lint/build checks locally
- [ ] I ran the relevant frontend and/or backend checks locally
- [ ] I updated docs/comments where relevant
- [ ] I added screenshots or short demo notes for UI changes
- [ ] I updated tests when changing API behavior or UI flows
- [ ] My PR title clearly describes the change
- [ ] My PR description explains:
- what changed
Expand All @@ -76,6 +94,7 @@ Examples:
- Follow existing patterns in the project
- Keep components and functions small and focused
- Avoid unrelated changes in the same PR
- For API changes, keep `backend/app.py`, `frontend/src/App.jsx`, and related tests in sync

## Reporting Issues

Expand Down
66 changes: 65 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,69 @@
# github-agentic-workflows

A React + Flask application. The React frontend communicates with a Flask API backend.

## Project Structure

```
.
├── backend/ # Flask API
│ ├── app.py
│ ├── requirements.txt
│ └── test_app.py
└── frontend/ # React (Vite)
├── src/
│ ├── App.jsx
│ └── test/
├── package.json
└── vite.config.js
```

## Getting Started

### Backend

```bash
cd backend
pip install -r requirements.txt
python app.py
```

The Flask API runs on `http://localhost:5000`.

### Frontend

```bash
cd frontend
npm install
npm run dev
```

The React app runs on `http://localhost:5173` and proxies `/api` requests to the Flask backend.

## API Endpoints

| Method | Path | Description |
|--------|------|-------------|
| GET | `/api/health` | Health check |
| GET | `/api/items` | List all items |
| POST | `/api/items` | Create an item (`{"name": "..."}`) |
| DELETE | `/api/items/:id` | Delete an item |

## Running Tests

**Backend**

```bash
cd backend
python -m pytest test_app.py -v
```

**Frontend**

```bash
cd frontend
npm test
```
## github next agentics

```sh
Expand Down Expand Up @@ -93,4 +157,4 @@ gh aw add-wizard githubnext/agentics/repo-ask
# Add the workflow to your repository
gh aw add-wizard githubnext/agentics/pr-fix

```
```
54 changes: 54 additions & 0 deletions backend/app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import os
from flask import Flask, jsonify, request
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/grumpy

from flask_cors import CORS

app = Flask(__name__)
CORS(app)

# In-memory store for items
items = [
{"id": 1, "name": "Item One"},
{"id": 2, "name": "Item Two"},
]
next_id = 3


@app.route("/api/health", methods=["GET"])
def health():
"""Health check endpoint."""
return jsonify({"status": "ok"})


@app.route("/api/items", methods=["GET"])
def get_items():
"""Return all items."""
return jsonify(items)


@app.route("/api/items", methods=["POST"])
def create_item():
"""Create a new item."""
global next_id
data = request.get_json()
if not data or not data.get("name"):
return jsonify({"error": "name is required"}), 400
item = {"id": next_id, "name": data["name"]}
next_id += 1
items.append(item)
return jsonify(item), 201


@app.route("/api/items/<int:item_id>", methods=["DELETE"])
def delete_item(item_id):
"""Delete an item by id."""
global items
original_len = len(items)
items = [i for i in items if i["id"] != item_id]
if len(items) == original_len:
return jsonify({"error": "item not found"}), 404
return jsonify({"deleted": item_id})


if __name__ == "__main__":
debug = os.environ.get("FLASK_DEBUG", "false").lower() == "true"
app.run(debug=debug, port=5000)
3 changes: 3 additions & 0 deletions backend/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
flask>=3.1.0
flask-cors>=5.0.0
pytest>=8.0.0
61 changes: 61 additions & 0 deletions backend/test_app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import pytest
from app import app, items


@pytest.fixture(autouse=True)
def reset_items():
"""Reset items list and next_id before each test."""
import app as app_module
app_module.items = [
{"id": 1, "name": "Item One"},
{"id": 2, "name": "Item Two"},
]
app_module.next_id = 3
yield


@pytest.fixture
def client():
app.config["TESTING"] = True
with app.test_client() as client:
yield client


def test_health(client):
response = client.get("/api/health")
assert response.status_code == 200
assert response.get_json() == {"status": "ok"}


def test_get_items(client):
response = client.get("/api/items")
assert response.status_code == 200
data = response.get_json()
assert len(data) == 2
assert data[0]["name"] == "Item One"


def test_create_item(client):
response = client.post("/api/items", json={"name": "New Item"})
assert response.status_code == 201
data = response.get_json()
assert data["name"] == "New Item"
assert "id" in data


def test_create_item_missing_name(client):
response = client.post("/api/items", json={})
assert response.status_code == 400
assert "error" in response.get_json()


def test_delete_item(client):
response = client.delete("/api/items/1")
assert response.status_code == 200
assert response.get_json()["deleted"] == 1


def test_delete_item_not_found(client):
response = client.delete("/api/items/999")
assert response.status_code == 404
assert "error" in response.get_json()
File renamed without changes.
File renamed without changes.
File renamed without changes.
2 changes: 1 addition & 1 deletion src/ui/index.html → frontend/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>my-react-app</title>
<title>frontend</title>
</head>
<body>
<div id="root"></div>
Expand Down
Loading
Loading