Skip to content

Commit a076417

Browse files
committed
ci: make the template reproducible in GitHub Actions and dev containers
A reusable template needs consistent execution outside one laptop. This adds GitHub Actions for quality, build, audit, and tag-based release artifacts, plus a dev container and top-level README so teammates get the same bootstrap path in CI and in editor-based Linux environments. Constraint: The default automation must stay generic enough for pure Python projects while still fitting robotics and ML teams Rejected: Bake ROS 2 and GPU-specific setup directly into the base workflows | too heavy and too environment-specific for a starter template Confidence: high Scope-risk: moderate Reversibility: clean Directive: Keep CI fast on the core path; isolate heavier robotics or platform-specific checks into opt-in workflows later Tested: uv lock; uv sync --group dev; make check; make build; make run-example-ml; make run-example-robotics; make audit; JSON/YAML parse of devcontainer and workflow files Not-tested: Actual GitHub-hosted runner execution and Codespaces startup behavior
1 parent 9ff165c commit a076417

6 files changed

Lines changed: 281 additions & 0 deletions

File tree

.devcontainer/devcontainer.json

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
{
2+
"name": "python-template",
3+
"image": "mcr.microsoft.com/devcontainers/python:1-3.12-bookworm",
4+
"features": {
5+
"ghcr.io/devcontainers/features/common-utils:2": {
6+
"installZsh": false,
7+
"username": "vscode"
8+
}
9+
},
10+
"postCreateCommand": "curl -LsSf https://astral.sh/uv/install.sh | sh && $HOME/.local/bin/uv sync --group dev",
11+
"customizations": {
12+
"vscode": {
13+
"extensions": [
14+
"ms-python.python",
15+
"ms-python.vscode-pylance",
16+
"charliermarsh.ruff",
17+
"github.vscode-github-actions"
18+
],
19+
"settings": {
20+
"python.defaultInterpreterPath": "${containerWorkspaceFolder}/.venv/bin/python",
21+
"editor.formatOnSave": true,
22+
"editor.codeActionsOnSave": {
23+
"source.fixAll.ruff": "explicit"
24+
}
25+
}
26+
}
27+
}
28+
}

.github/workflows/audit.yml

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
name: Audit
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
- feature/**
8+
pull_request:
9+
schedule:
10+
- cron: '0 3 * * 1'
11+
workflow_dispatch:
12+
13+
permissions:
14+
contents: read
15+
16+
jobs:
17+
audit:
18+
runs-on: ubuntu-latest
19+
steps:
20+
- uses: actions/checkout@v6
21+
- uses: actions/setup-python@v6
22+
with:
23+
python-version: '3.12'
24+
- uses: astral-sh/setup-uv@v7
25+
with:
26+
enable-cache: true
27+
- name: Sync dependencies
28+
run: uv sync --group dev --all-extras --frozen
29+
- name: Run pip-audit
30+
run: make audit

.github/workflows/build.yml

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
name: Build
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
- feature/**
8+
pull_request:
9+
workflow_dispatch:
10+
11+
permissions:
12+
contents: read
13+
14+
jobs:
15+
build:
16+
runs-on: ubuntu-latest
17+
steps:
18+
- uses: actions/checkout@v6
19+
- uses: actions/setup-python@v6
20+
with:
21+
python-version-file: .python-version
22+
- uses: astral-sh/setup-uv@v7
23+
with:
24+
enable-cache: true
25+
- name: Sync dependencies
26+
run: uv sync --group dev --frozen
27+
- name: Build wheel and sdist
28+
run: make build
29+
- name: Smoke-test built wheel
30+
run: |
31+
python -m venv /tmp/python-template-wheel-test
32+
/tmp/python-template-wheel-test/bin/pip install dist/*.whl
33+
/tmp/python-template-wheel-test/bin/python -m python_template
34+
- name: Upload build artifacts
35+
uses: actions/upload-artifact@v4
36+
with:
37+
name: python-package-dist
38+
path: dist/

.github/workflows/ci.yml

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
- feature/**
8+
pull_request:
9+
10+
permissions:
11+
contents: read
12+
13+
jobs:
14+
quality:
15+
name: quality (${{ matrix.os }}, py${{ matrix.python-version }})
16+
runs-on: ${{ matrix.os }}
17+
strategy:
18+
fail-fast: false
19+
matrix:
20+
include:
21+
- os: ubuntu-latest
22+
python-version: '3.11'
23+
- os: ubuntu-latest
24+
python-version: '3.12'
25+
- os: ubuntu-latest
26+
python-version: '3.13'
27+
- os: macos-latest
28+
python-version: '3.12'
29+
steps:
30+
- uses: actions/checkout@v6
31+
- uses: actions/setup-python@v6
32+
with:
33+
python-version: ${{ matrix.python-version }}
34+
- uses: astral-sh/setup-uv@v7
35+
with:
36+
enable-cache: true
37+
- name: Sync dependencies
38+
run: uv sync --group dev --frozen
39+
- name: Run quality gate
40+
run: make check
41+
42+
examples:
43+
name: examples (ubuntu, py3.12)
44+
runs-on: ubuntu-latest
45+
steps:
46+
- uses: actions/checkout@v6
47+
- uses: actions/setup-python@v6
48+
with:
49+
python-version: '3.12'
50+
- uses: astral-sh/setup-uv@v7
51+
with:
52+
enable-cache: true
53+
- name: Sync dependencies
54+
run: uv sync --group dev --frozen
55+
- name: Run example stubs
56+
run: |
57+
make run-example-ml
58+
make run-example-robotics

.github/workflows/release.yml

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
name: Release
2+
3+
on:
4+
push:
5+
tags:
6+
- 'v*'
7+
workflow_dispatch:
8+
9+
permissions:
10+
contents: read
11+
12+
jobs:
13+
release-artifacts:
14+
runs-on: ubuntu-latest
15+
steps:
16+
- uses: actions/checkout@v6
17+
- uses: actions/setup-python@v6
18+
with:
19+
python-version-file: .python-version
20+
- uses: astral-sh/setup-uv@v7
21+
with:
22+
enable-cache: true
23+
- name: Sync dependencies
24+
run: uv sync --group dev --frozen
25+
- name: Build release artifacts
26+
run: make build
27+
- name: Upload release artifacts
28+
uses: actions/upload-artifact@v4
29+
with:
30+
name: python-template-release-${{ github.ref_name }}
31+
path: dist/

README.md

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,97 @@
11
# python-template
2+
3+
A modern Python template for robotics and ML teams that want fast local iteration, reproducible
4+
setup, and CI-enforced quality gates.
5+
6+
## Why this template
7+
8+
This scaffold is optimized for hybrid robotics + ML work:
9+
10+
- **`uv` first** for fast environment and lockfile management
11+
- **`pyproject.toml` + `src/` layout** for modern packaging
12+
- **Ruff + Pyright + pytest** for a strong default quality bar
13+
- **Makefile** as the single memorable task surface for developers and CI
14+
- **GitHub Actions** for repeatable checks on Python 3.11–3.13
15+
- **Optional extras** so robotics/ML dependencies do not bloat the base environment
16+
17+
## Quickstart
18+
19+
```bash
20+
uv sync --group dev
21+
make check
22+
make run-example-ml
23+
make run-example-robotics
24+
```
25+
26+
To install optional profiles:
27+
28+
```bash
29+
uv sync --group dev --extra ml
30+
uv sync --group dev --extra robotics
31+
uv sync --group dev --all-extras
32+
```
33+
34+
## Core tasks
35+
36+
| Task | Purpose |
37+
| --- | --- |
38+
| `make sync` | Install the base project environment |
39+
| `make sync-dev` | Install developer dependencies |
40+
| `make sync-all` | Install developer dependencies and all optional extras |
41+
| `make fmt` | Format source, tests, and examples |
42+
| `make lint` | Run Ruff lint checks |
43+
| `make typecheck` | Run Pyright |
44+
| `make test` | Run pytest |
45+
| `make test-cov` | Run pytest with coverage |
46+
| `make check` | Run format, lint, typecheck, and tests |
47+
| `make build` | Build wheel and sdist |
48+
| `make audit` | Run dependency vulnerability checks |
49+
| `make run-example-ml` | Execute the ML stub |
50+
| `make run-example-robotics` | Execute the robotics stub |
51+
52+
## Project layout
53+
54+
```text
55+
.
56+
├── .devcontainer/
57+
├── .github/workflows/
58+
├── docs/
59+
├── examples/
60+
│ ├── ml/
61+
│ └── robotics/
62+
├── src/python_template/
63+
└── tests/
64+
```
65+
66+
## Quality workflow
67+
68+
Local and CI use the same contract:
69+
70+
```bash
71+
make check
72+
make build
73+
```
74+
75+
That keeps the README, local workflow, and GitHub Actions aligned.
76+
77+
## Profiles
78+
79+
- `ml`: data-science friendly optional dependencies for training/evaluation prototypes
80+
- `robotics`: lightweight robotics-adjacent dependencies for adapters and integration code
81+
- `viz`: visualization and richer terminal output helpers
82+
83+
See [`docs/ml.md`](docs/ml.md) and [`docs/robotics.md`](docs/robotics.md) for guidance.
84+
85+
## GitHub Actions
86+
87+
The repository ships with:
88+
89+
- `ci.yml` for lint/type/test matrix checks
90+
- `build.yml` for build + wheel smoke validation
91+
- `audit.yml` for dependency auditing
92+
- `release.yml` for tag-driven build artifacts
93+
94+
## Dev container
95+
96+
The included dev container is meant to give teammates a reproducible Linux environment with `uv`
97+
installed and the dev dependencies synced on first open.

0 commit comments

Comments
 (0)