Make both distributions fit to publish
The release workflow was already right; what it would have uploaded was not. `fluksio` had no readme, so its PyPI page would have been blank — the app repo's own README is a contributor's map of `frontend/` and `docker/`, which is the wrong front page for `pip install fluksio`. It now has one of its own, aimed at somebody who landed on the project page. Both distributions gain authors, urls, keywords and classifiers; `twine check` passes clean on all four artifacts where it warned on two before. The workflow publishes `fluksio-worker` first, because `fluksio` depends on it and the other order leaves a few seconds — the whole of a first release — in which the dependency cannot be resolved. `--check-url` makes a re-run skip what is already uploaded rather than failing on it, which matters because a version on PyPI can never be replaced. Licence metadata is deliberately still absent: LICENSE is MIT in somebody else's name, inherited from the template this was scaffolded from, and whose it should be is not a decision to make in a commit. NOTEPAD carries it. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012ue1tkFWB1bcGy3aWhCKpU
This commit is contained in:
@@ -42,4 +42,15 @@ jobs:
|
|||||||
- name: Publish
|
- name: Publish
|
||||||
env:
|
env:
|
||||||
UV_PUBLISH_TOKEN: ${{ secrets.PYPI_TOKEN }}
|
UV_PUBLISH_TOKEN: ${{ secrets.PYPI_TOKEN }}
|
||||||
run: uv publish dist/*
|
# The worker first: `fluksio` depends on it, and for the seconds
|
||||||
|
# between two uploads the other order leaves a dependency that cannot
|
||||||
|
# be resolved — which on a first release is the whole of the window in
|
||||||
|
# which the package exists at all.
|
||||||
|
#
|
||||||
|
# `--check-url` makes a re-run skip what is already up there rather
|
||||||
|
# than failing on it, so a job that died between the two uploads can
|
||||||
|
# simply be run again. A version on PyPI can never be replaced, and
|
||||||
|
# this is the difference between retrying and burning a version.
|
||||||
|
run: |
|
||||||
|
uv publish --check-url https://pypi.org/simple/ dist/fluksio_worker-*
|
||||||
|
uv publish --check-url https://pypi.org/simple/ dist/fluksio-0*
|
||||||
|
|||||||
@@ -0,0 +1,76 @@
|
|||||||
|
# Fluksio
|
||||||
|
|
||||||
|
A node-based automation engine: flows, dashboards and batch runs, in one
|
||||||
|
resident process with no infrastructure behind it.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
pip install fluksio
|
||||||
|
fluksio serve
|
||||||
|
```
|
||||||
|
|
||||||
|
That is the whole installation — no Docker, no database server, no ports to
|
||||||
|
open. It keeps a SQLite database, a git repository of your flows and an
|
||||||
|
artifact store under `~/.fluksio`, and prints an admin password once.
|
||||||
|
|
||||||
|
## For data science
|
||||||
|
|
||||||
|
Your functions become nodes where they already live. Install Fluksio into the
|
||||||
|
environment you work in and your nodes run on it — the packages are already
|
||||||
|
there:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# myresearch/train.py
|
||||||
|
import fluksio
|
||||||
|
from fluksio import Port, node
|
||||||
|
|
||||||
|
@node(
|
||||||
|
requires=["dataset", Port("lr", "float")],
|
||||||
|
provides=[Port("loss", "float", stream=True), Port("weights", "artifact")],
|
||||||
|
device="gpu", device_policy="prefer",
|
||||||
|
)
|
||||||
|
def fit(dataset, lr, epochs=25):
|
||||||
|
for epoch in range(epochs):
|
||||||
|
loss = step(...)
|
||||||
|
yield {"loss": loss} # published as it happens, kept as a series
|
||||||
|
return {"weights": fluksio.save_artifact("weights.pt")}
|
||||||
|
```
|
||||||
|
|
||||||
|
```python
|
||||||
|
# myresearch/pipeline.py
|
||||||
|
from fluksio import Flow, Port
|
||||||
|
from myresearch.train import fit
|
||||||
|
|
||||||
|
train = Flow("train", nodes=[prepare, fit, evaluate],
|
||||||
|
inputs=[Port("lr", "float", initial=0.01)], outputs=["score"])
|
||||||
|
```
|
||||||
|
|
||||||
|
```sh
|
||||||
|
fluksio login --url http://127.0.0.1:8000
|
||||||
|
fluksio sync myresearch
|
||||||
|
fluksio run train --lr 0.05 --wait
|
||||||
|
```
|
||||||
|
|
||||||
|
The decorators return your functions untouched, so everything stays callable,
|
||||||
|
testable and importable as what it was. A metric leaves through a declared
|
||||||
|
port rather than a logging call, which is why there is no `log_metric()`: the
|
||||||
|
run keeps the whole series, a chart can bind to it, and a downstream node can
|
||||||
|
consume it.
|
||||||
|
|
||||||
|
## What else it does
|
||||||
|
|
||||||
|
- **Flows** — typed messages between nodes, wired by name, edited on a canvas
|
||||||
|
or declared in code. Every change is a commit in a git repository you own.
|
||||||
|
- **Runs** — an experiment and a CI-style job are the same entity. Parameters,
|
||||||
|
seed, result, per-node timings, artifacts and the commit it ran at.
|
||||||
|
- **Dashboards** — charts and controls bound to the same messages the flows
|
||||||
|
carry, with no separate metrics pipeline.
|
||||||
|
- **Remote workers** — `pip install fluksio-worker` on the GPU box; it dials
|
||||||
|
*out* over one websocket, so nothing there has to be reachable.
|
||||||
|
|
||||||
|
## Links
|
||||||
|
|
||||||
|
- Documentation: <https://docs.fluksio.com>
|
||||||
|
- Getting started (data science): <https://docs.fluksio.com/getting-started/data-science/>
|
||||||
|
- Home: <https://fluksio.com>
|
||||||
|
|
||||||
|
Python 3.10 or newer, Linux or macOS.
|
||||||
@@ -2,7 +2,25 @@
|
|||||||
name = "fluksio"
|
name = "fluksio"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
description = "Node-based automation engine: flows, dashboards, batch runs"
|
description = "Node-based automation engine: flows, dashboards, batch runs"
|
||||||
|
readme = "README.md"
|
||||||
requires-python = ">=3.10"
|
requires-python = ">=3.10"
|
||||||
|
authors = [{ name = "Fluksio", email = "stroblme@posteo.de" }]
|
||||||
|
keywords = ["automation", "workflow", "dataflow", "experiment-tracking", "mlops"]
|
||||||
|
classifiers = [
|
||||||
|
"Development Status :: 3 - Alpha",
|
||||||
|
"Intended Audience :: Developers",
|
||||||
|
"Intended Audience :: Science/Research",
|
||||||
|
"Operating System :: MacOS",
|
||||||
|
"Operating System :: POSIX :: Linux",
|
||||||
|
"Programming Language :: Python :: 3",
|
||||||
|
"Programming Language :: Python :: 3.10",
|
||||||
|
"Programming Language :: Python :: 3.11",
|
||||||
|
"Programming Language :: Python :: 3.12",
|
||||||
|
"Programming Language :: Python :: 3.13",
|
||||||
|
"Topic :: Home Automation",
|
||||||
|
"Topic :: Scientific/Engineering",
|
||||||
|
"Topic :: System :: Distributed Computing",
|
||||||
|
]
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"fastapi[standard]<1.0.0,>=0.114.2",
|
"fastapi[standard]<1.0.0,>=0.114.2",
|
||||||
"python-multipart<1.0.0,>=0.0.7",
|
"python-multipart<1.0.0,>=0.0.7",
|
||||||
@@ -32,6 +50,11 @@ dependencies = [
|
|||||||
"uv>=0.5",
|
"uv>=0.5",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[project.urls]
|
||||||
|
Homepage = "https://fluksio.com"
|
||||||
|
Documentation = "https://docs.fluksio.com"
|
||||||
|
"Getting started" = "https://docs.fluksio.com/getting-started/data-science/"
|
||||||
|
|
||||||
[project.scripts]
|
[project.scripts]
|
||||||
fluksio = "fluksio.cli:main"
|
fluksio = "fluksio.cli:main"
|
||||||
|
|
||||||
|
|||||||
@@ -4,10 +4,31 @@ version = "0.1.0"
|
|||||||
description = "Runs Fluksio nodes on a machine the engine cannot reach"
|
description = "Runs Fluksio nodes on a machine the engine cannot reach"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
requires-python = ">=3.10"
|
requires-python = ">=3.10"
|
||||||
|
authors = [{ name = "Fluksio", email = "stroblme@posteo.de" }]
|
||||||
|
keywords = ["automation", "workflow", "distributed", "worker", "gpu"]
|
||||||
|
classifiers = [
|
||||||
|
"Development Status :: 3 - Alpha",
|
||||||
|
"Intended Audience :: Developers",
|
||||||
|
"Intended Audience :: Science/Research",
|
||||||
|
"Operating System :: MacOS",
|
||||||
|
"Operating System :: POSIX :: Linux",
|
||||||
|
"Programming Language :: Python :: 3",
|
||||||
|
"Programming Language :: Python :: 3.10",
|
||||||
|
"Programming Language :: Python :: 3.11",
|
||||||
|
"Programming Language :: Python :: 3.12",
|
||||||
|
"Programming Language :: Python :: 3.13",
|
||||||
|
"Topic :: Home Automation",
|
||||||
|
"Topic :: Scientific/Engineering",
|
||||||
|
"Topic :: System :: Distributed Computing",
|
||||||
|
]
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"websockets>=12",
|
"websockets>=12",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[project.urls]
|
||||||
|
Homepage = "https://fluksio.com"
|
||||||
|
Documentation = "https://docs.fluksio.com/code/workers/"
|
||||||
|
|
||||||
[project.scripts]
|
[project.scripts]
|
||||||
fluksio-worker = "fluksio_worker.agent:main"
|
fluksio-worker = "fluksio_worker.agent:main"
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user