Releases: dexadata/dexaflow
Release list
v0.5.0
Dexaflow v0.5.0
A 0.x (pre-1.0) build — SemVer carries the maturity, there is no separate
alpha/beta, and the pre-alpha series ended at v0.0.1 (ADR 0037). APIs and
on-disk shape may still evolve between minor versions; -rc.N tags are release
candidates gated by the E2E suite. Install this exact release with:
curl -fsSL https://raw.githubusercontent.com/dexadata/dexaflow/v0.5.0/install.sh | LEOFLOW_VERSION=v0.5.0 shA bare
curl … | shinstalls the latest stable release (/releases/latest
excludes pre-releases), so on a pre-release page it would NOT give youv0.5.0.
LEOFLOW_VERSIONmust sit on theshside of the pipe (notcurl) — a
VAR=x curl … | shprefix sets the var forcurlonly, soinstall.shwould
not see it and would fall back to latest-stable.
Added
-
A reference page for every image and chart a release publishes, and the
tag scheme for each: Published
images.
The only page that namedleoflow-server,leoflow-migrateand
leoflow-runtimetogether was a maintainer page about scanning them, so an
operator asking what Dexaflow publishes and how it is tagged had nowhere to
read.It also writes down a rule that lived only in the code: when
base_imageis
unset, a releaseddexaflowpinsdexaflow-runtime:py<ver>-v<X.Y.Z>, which
is immutable, while a development build falls back to
leoflow-runtime:py<ver>, a line every release republishes. Two people
compiling the same project can therefore end up on different bases, and
nothing said so. The configuration reference now says it where a reader is
already deciding whether to pin. -
An optional link from the UI back to the platform you serve it from
(#1290). Operators who run Dexaflow inside an internal portal or a hosting
console can setui.home_link.labelandui.home_link.url(Helm:
ui.homeLink), and every UI page shows a small "back" pill at the
bottom-left that opens the URL in the same tab. It is off by default. Boot
fails on a URL that is not absolutehttp://orhttps://, or on a label
without a URL, so a typo never renders a dead or script-bearing link. -
Brand the UI by configuration (#1289).
ui.themetakes a JSON object in
the shape of Airflow's[api] theme(Chakratokenssuch as the brand
palette and fonts,globalCss,icon,icon_dark_mode) and serves it in
/ui/config, so the bundled UI applies it through its own theming instead of
a patched bundle.ui.favicon_urlreplaces the favicon and
ui.stylesheet_urlsloads extra stylesheets such as web fonts. Helm:
ui.theme,ui.faviconUrl,ui.stylesheetUrls. All off by default; boot
fails on invalid theme JSON, an unknown theme key, or a URL that is not
http(s) or root-relative. See Branding the
UI. -
Hand sign-in and sign-out to the platform Dexaflow is served from
(#1288). Withauth.external_signin_urlset, a UI visitor without a session
goes to that URL with the page they asked for innext, instead of
Dexaflow's sign-in page, so deep links survive.auth.external_signout_url
is where sign-out lands after clearing the session. Helm:
auth.externalSigninUrl,auth.externalSignoutUrl. Off by default;
?local=1and a refused single sign-on still reach Dexaflow's own page, and
boot fails on anything but an absolutehttp(s)URL. -
Open a UI session from a trusted issuer's token (#1284). A platform that
already signs its users in can now hand them to Dexaflow without Dexaflow
storing a password and without the platform holding Dexaflow's signing
secret: configureauth.trusted_issuer(issuer, JWKS URL, audience, tenant
claim, allowed tenants, allowed origins; Helm:auth.trustedIssuer) and post
a short-lived token the issuer signed toPOST /api/v2/auth/sessionfrom a
page on one of the allowed origins. Dexaflow verifies it
against the issuer's public keys, signs in the existing active user linked
to the token's subject in the token's tenant, and redirects tonext. The
token never creates users or grants roles, carries ajtiand opens one
session (a replayedjtiis refused), and lives at most two minutes by
default (max_lifetime_seconds, up to 600). Off by default, validated at boot,
and keys are fetched on first use so an issuer outage cannot block boot. See
Trusted-issuer
handoff. -
An operator service API to create tenants and passwordless users
(#1283). Withauth.service_tokenset (Helm:auth.serviceTokenor
auth.serviceTokenExistingSecret),PUT /api/v2/service/tenants/{tenant}
creates a tenant with the same built-in roles, permissions and default pool
asdefault, andPUT /api/v2/service/tenants/{tenant}/users/{subject}
makes sure a user with no password exists there, linked to the trusted
issuer under that subject, with exactly the roles given. Both are idempotent
and authenticate with the service token, never a user session. Users are
linked only in tenants the trusted issuer may sign in to, and every call is
recorded in the audit trail. Off by default. The OIDC boot warning about a missing tenant now names the service
API as the way to create one. See Operator service
API.
Changed
-
Leoflow is now Dexaflow. Messages, the login and IDE pages, the UI navbar,
the docs and the README use the new name and thedexaflowcommands. The
README and a new "The name" page tell where both names come from, and keep the
dedication to Leonardo (@leonardo-jas),
after whom Leoflow was named. Everything adopted under the old name keeps
working; the configuration reference lists each one. -
Images and the chart are published as
dexaflow-*andcharts/dexaflow,
and every release is still published under theleoflownames. Each
release pushesdexaflow-server,dexaflow-migrateanddexaflow-runtime,
and the same builds asleoflow-server,leoflow-migrateand
leoflow-runtime: same tags, same digests, all signed. Values files,
Dockerfiles andFROMlines that nameleoflow-*keep receiving new
releases without a change. The chart's image defaults and the runtime base
dexaflow compilebuilds on are thedexaflow-*names.The chart is published twice from the same templates:
charts/dexaflowfor
new installs andcharts/leoflowfor releases installed before the rename.
The chart name decides the selector labels and every resource name, and a
Deployment's selector cannot change in place, so an existing release is
upgraded withoci://ghcr.io/dexadata/charts/leoflow(or with the
dexaflowchart and--set nameOverride=leoflow, which renders the same
resources). The CI upgrade guard now upgrades a released install exactly
that way. -
New installs keep their DAG projects in
~/dexaflow. An install from
before the rename that has~/leoflowkeeps using it as the default
workspace, and a workspace recorded bydexaflow setupis used as is, so no
project moves. The bundle installer copies its DAGs into the recorded
workspace. Messages that still named the olddevcommand now say
dexaflow lite. -
DAGs import the authoring names from
dexaflow, andfrom leoflow import dbt_groupkeeps working. The package adag.pyimports at its top is now
dexaflow, at parse time and inside task images and Lite venvs alike.
leoflowis a re-export of it, not a copy:leoflow.dbt_group is dexaflow.dbt_group, so DAGs written before the rename compile and run
unchanged, and the two can never drift apart.A Lite venv built before this release has no
dexaflowpackage; the
freshness check now probes for it, so the venv is rebuilt once on the next
dexaflow liteinstead of everyfrom dexaflow import ...failing in the pod.The internal modules
leoflow_runtimeandleoflow_parserkeep their names:
agents in already built task images runpython -m leoflow_runtime, and the
parser_cmdin existingconfig.yamlfiles namesleoflow_parser. -
Metrics are named
dexaflow_*, and every family is still published as
leoflow_*. The control plane's/metricsendpoint exposes each
dexaflow_*family a second time under its pre-rename name, with the same
help, type, labels and values, so dashboards, alerts and recording rules
written againstleoflow_*keep working without a change. Moving a dashboard
to the new names is a rename of the metric, not of anything else. Each family
appears twice in a scrape; series counts for these families double.The soak monitor reads either name and counts each family once, so it keeps
working against control planes from before this release. -
The documentation moves to its own domain, https://dexaflow.dexadata.ai/.
The site used to live athttps://neochaotic.github.io/leoflow/, an address
tied to the account that owns the repository, so moving the repository would
have broken every link to the docs. Serving the site from a custom domain
decouples the two. The/leoflow/path prefix goes away with it: the latest
release is at the root,mainat/dev/, and archived releases at
/vX.Y.Z/, as before. Oldneochaotic.github.io/leoflow/...links redirect
to the same page on the new domain.The README's Pro install snippet also stops pointing
helm repo addat the
docs site, which never served a chart index. It now installs from the OCI
chart in GHCR, where the chart is actually published. -
The repository is now
github.com/dexadata/dexaflow. It moved from
neochaotic/leoflowto the DexaData organization and took the new...
v0.5.0-rc.1
Dexaflow v0.5.0-rc.1
A 0.x (pre-1.0) build — SemVer carries the maturity, there is no separate
alpha/beta, and the pre-alpha series ended at v0.0.1 (ADR 0037). APIs and
on-disk shape may still evolve between minor versions; -rc.N tags are release
candidates gated by the E2E suite. Install this exact release with:
curl -fsSL https://raw.githubusercontent.com/dexadata/dexaflow/v0.5.0-rc.1/install.sh | LEOFLOW_VERSION=v0.5.0-rc.1 shA bare
curl … | shinstalls the latest stable release (/releases/latest
excludes pre-releases), so on a pre-release page it would NOT give youv0.5.0-rc.1.
LEOFLOW_VERSIONmust sit on theshside of the pipe (notcurl) — a
VAR=x curl … | shprefix sets the var forcurlonly, soinstall.shwould
not see it and would fall back to latest-stable.
Added
-
A reference page for every image and chart a release publishes, and the
tag scheme for each: Published
images.
The only page that namedleoflow-server,leoflow-migrateand
leoflow-runtimetogether was a maintainer page about scanning them, so an
operator asking what Dexaflow publishes and how it is tagged had nowhere to
read.It also writes down a rule that lived only in the code: when
base_imageis
unset, a releasedleoflowpinsleoflow-runtime:py<ver>-v<X.Y.Z>, which
is immutable, while a development build falls back to
leoflow-runtime:py<ver>, a line every release republishes. Two people
compiling the same project can therefore end up on different bases, and
nothing said so. The configuration reference now says it where a reader is
already deciding whether to pin. -
An optional link from the UI back to the platform you serve it from
(#1290). Operators who run Dexaflow inside an internal portal or a hosting
console can setui.home_link.labelandui.home_link.url(Helm:
ui.homeLink), and every UI page shows a small "back" pill at the
bottom-left that opens the URL in the same tab. It is off by default. Boot
fails on a URL that is not absolutehttp://orhttps://, or on a label
without a URL, so a typo never renders a dead or script-bearing link. -
Brand the UI by configuration (#1289).
ui.themetakes a JSON object in
the shape of Airflow's[api] theme(Chakratokenssuch as the brand
palette and fonts,globalCss,icon,icon_dark_mode) and serves it in
/ui/config, so the bundled UI applies it through its own theming instead of
a patched bundle.ui.favicon_urlreplaces the favicon and
ui.stylesheet_urlsloads extra stylesheets such as web fonts. Helm:
ui.theme,ui.faviconUrl,ui.stylesheetUrls. All off by default; boot
fails on invalid theme JSON, an unknown theme key, or a URL that is not
http(s) or root-relative. See Branding the
UI. -
Hand sign-in and sign-out to the platform Dexaflow is served from
(#1288). Withauth.external_signin_urlset, a UI visitor without a session
goes to that URL with the page they asked for innext, instead of
Dexaflow's sign-in page, so deep links survive.auth.external_signout_url
is where sign-out lands after clearing the session. Helm:
auth.externalSigninUrl,auth.externalSignoutUrl. Off by default;
?local=1and a refused single sign-on still reach Dexaflow's own page, and
boot fails on anything but an absolutehttp(s)URL. -
Open a UI session from a trusted issuer's token (#1284). A platform that
already signs its users in can now hand them to Dexaflow without Dexaflow
storing a password and without the platform holding Dexaflow's signing
secret: configureauth.trusted_issuer(issuer, JWKS URL, audience, tenant
claim, allowed tenants, allowed origins; Helm:auth.trustedIssuer) and post
a short-lived token the issuer signed toPOST /api/v2/auth/sessionfrom a
page on one of the allowed origins. Dexaflow verifies it
against the issuer's public keys, signs in the existing active user linked
to the token's subject in the token's tenant, and redirects tonext. The
token never creates users or grants roles, carries ajtiand opens one
session (a replayedjtiis refused), and lives at most two minutes by
default (max_lifetime_seconds, up to 600). Off by default, validated at boot,
and keys are fetched on first use so an issuer outage cannot block boot. See
Trusted-issuer
handoff. -
An operator service API to create tenants and passwordless users
(#1283). Withauth.service_tokenset (Helm:auth.serviceTokenor
auth.serviceTokenExistingSecret),PUT /api/v2/service/tenants/{tenant}
creates a tenant with the same built-in roles, permissions and default pool
asdefault, andPUT /api/v2/service/tenants/{tenant}/users/{subject}
makes sure a user with no password exists there, linked to the trusted
issuer under that subject, with exactly the roles given. Both are idempotent
and authenticate with the service token, never a user session. Users are
linked only in tenants the trusted issuer may sign in to, and every call is
recorded in the audit trail. Off by default. The OIDC boot warning about a missing tenant now names the service
API as the way to create one. See Operator service
API.
Changed
-
Leoflow is now Dexaflow. Messages, the login and IDE pages, the UI navbar,
the docs and the README use the new name and thedexaflowcommands. The
README and a new "The name" page tell where both names come from, and keep the
dedication to Leonardo (@leonardo-jas),
after whom Leoflow was named. Everything adopted under the old name keeps
working; the configuration reference lists each one. -
Images and the chart are published as
dexaflow-*andcharts/dexaflow,
and every release is still published under theleoflownames. Each
release pushesdexaflow-server,dexaflow-migrateanddexaflow-runtime,
and the same builds asleoflow-server,leoflow-migrateand
leoflow-runtime: same tags, same digests, all signed. Values files,
Dockerfiles andFROMlines that nameleoflow-*keep receiving new
releases without a change. The chart's image defaults and the runtime base
dexaflow compilebuilds on are thedexaflow-*names.The chart is published twice from the same templates:
charts/dexaflowfor
new installs andcharts/leoflowfor releases installed before the rename.
The chart name decides the selector labels and every resource name, and a
Deployment's selector cannot change in place, so an existing release is
upgraded withoci://ghcr.io/dexadata/charts/leoflow(or with the
dexaflowchart and--set nameOverride=leoflow, which renders the same
resources). The CI upgrade guard now upgrades a released install exactly
that way. -
New installs keep their DAG projects in
~/dexaflow. An install from
before the rename that has~/leoflowkeeps using it as the default
workspace, and a workspace recorded bydexaflow setupis used as is, so no
project moves. The bundle installer copies its DAGs into the recorded
workspace. Messages that still named the olddevcommand now say
dexaflow lite. -
DAGs import the authoring names from
dexaflow, andfrom leoflow import dbt_groupkeeps working. The package adag.pyimports at its top is now
dexaflow, at parse time and inside task images and Lite venvs alike.
leoflowis a re-export of it, not a copy:leoflow.dbt_group is dexaflow.dbt_group, so DAGs written before the rename compile and run
unchanged, and the two can never drift apart.A Lite venv built before this release has no
dexaflowpackage; the
freshness check now probes for it, so the venv is rebuilt once on the next
dexaflow liteinstead of everyfrom dexaflow import ...failing in the pod.The internal modules
leoflow_runtimeandleoflow_parserkeep their names:
agents in already built task images runpython -m leoflow_runtime, and the
parser_cmdin existingconfig.yamlfiles namesleoflow_parser. -
Metrics are named
dexaflow_*, and every family is still published as
leoflow_*. The control plane's/metricsendpoint exposes each
dexaflow_*family a second time under its pre-rename name, with the same
help, type, labels and values, so dashboards, alerts and recording rules
written againstleoflow_*keep working without a change. Moving a dashboard
to the new names is a rename of the metric, not of anything else. Each family
appears twice in a scrape; series counts for these families double.The soak monitor reads either name and counts each family once, so it keeps
working against control planes from before this release. -
The documentation moves to its own domain, https://dexaflow.dexadata.ai/.
The site used to live athttps://neochaotic.github.io/leoflow/, an address
tied to the account that owns the repository, so moving the repository would
have broken every link to the docs. Serving the site from a custom domain
decouples the two. The/leoflow/path prefix goes away with it: the latest
release is at the root,mainat/dev/, and archived releases at
/vX.Y.Z/, as before. Oldneochaotic.github.io/leoflow/...links redirect
to the same page on the new domain.The README's Pro install snippet also stops pointing
helm repo addat the
docs site, which never served a chart index. It now installs from the OCI
chart in GHCR, where the chart is actually published. -
The repository is now
github.com/dexadata/dexaflow. It moved from
neochaotic/leoflowto the DexaData organizatio...
v0.4.8
Leoflow v0.4.8
A 0.x (pre-1.0) build — SemVer carries the maturity, there is no separate
alpha/beta, and the pre-alpha series ended at v0.0.1 (ADR 0037). APIs and
on-disk shape may still evolve between minor versions; -rc.N tags are release
candidates gated by the E2E suite. Install this exact release with:
curl -fsSL https://raw.githubusercontent.com/neochaotic/leoflow/v0.4.8/install.sh | LEOFLOW_VERSION=v0.4.8 shA bare
curl … | shinstalls the latest stable release (/releases/latest
excludes pre-releases), so on a pre-release page it would NOT give youv0.4.8.
LEOFLOW_VERSIONmust sit on theshside of the pipe (notcurl) — a
VAR=x curl … | shprefix sets the var forcurlonly, soinstall.shwould
not see it and would fall back to latest-stable.
Added
-
The UI refresh interval is settable from the chart
(ui.autoRefreshIntervalSeconds). It was reported that the Pro UI feels far
slower to update than Lite, and it does: Pro polls every 30s and Lite every 1s,
a thirty-fold difference. The setting to change it already existed and was
documented, and the chart modelled nothing, so a Helm operator could reach it
only throughextraEnv, which hides the behavior from anyone reading the
chart.The chart omits the variable entirely when unset rather than rendering an empty
one, so the server's default stays in charge and nobody goes looking in the
chart for a number the chart did not choose.This exposes the choice; it does not change the default. Copying Lite's 1s
would multiply request and query load by thirty per open tab, and Lite can
afford that only because it is one person against a local database. Choosing a
better default needs the cost of one refresh cycle measured, which is tracked
in #1196 along with the
question of whether polling is the right mechanism at all. -
A long-running resilience soak battery (
test/soak/). The gates we had
answer a different question:test/e2e/proves a path works once,test/load/
measures one cost at one instant, andchaos-runtime.shinjects a fault and
checks the recovery. None told us whether a control plane that has been
dispatching since Friday is still dispatching on Monday, or whether the cost of
a tick had started tracking the size of the history table rather than the
active set.make soakruns a realistic scheduled workload (six DAG projects spanning the
python,bashandairflow_operatortask types, with DuckDB generating the
data volume) against a dedicated local Postgres and asserts ten invariants on
every sample: wedge thresholds onqueued/scheduled/running, scheduler
health, run-creation cadence per DAG, leader churn, retry budget, archived-
attempt state, and terminal-run consistency. (The archived-attempt check is
cheap and holds, but it is not an at-most-once proof: seetest/soak/README.md
section 1 for exactly what it can and cannot catch.) Evidence is written
continuously
(samples.jsonlfsynced per record,summary.mdandverdict.jsonrewritten
atomically every sample), so a harness that is killed still leaves a current
report.make soak-selftestproves the assertions can fail: it injects a real 300 s
Postgres outage while declaring a 45 s window for it, and the run must exit
exactly 1 with recorded violations (exit 2, a harness that never ran, is a
failure of the self test, not a pass). Nothing is faked and no threshold is
relaxed.Everything runs locally and costs nothing: no cloud, no cluster, no paid
service, and no public HTTP endpoint anywhere in the workload (the operator leg
points at a loopback fixture server, and CI enforces that). Bounded by a
wall-clock ceiling, a disk budget with a clean stop, and a watchdog. Long runs
are scheduled locally viatest/soak/schedule/install.sh; CI runs only a
6-minute harness smoke, for the cost reasons documented in
test/soak/README.md. -
auth.session_cookie_insecure(defaultfalse), the one escape hatch the
fix above needs.Secureis now decided by the server rather than by the
page'slocation.protocol, and a browser refuses aSecurecookie from a
plain-http origin that is not loopback, so a deployment served over plain http
to a real hostname would otherwise have been upgraded into a sign-in page that
posts valid credentials, gets a200, and lands back on itself. It cannot be
derived from the request: behind a TLS-terminating ingress the server sees
plain http while the browser sees https, so request-derivedSecurewould
strip it from the deployment that most needs it. Operator-scoped,WARNat
boot while it is on, and no Helm value on purpose. -
auth.oidc.auto_redirectstarts the flow instead of showing the sign-in
page. Off by default. Where an edge proxy has already authenticated the
session, or SSO is the only way in, that page was a screen to acknowledge for
nothing; a comparable tool against the same identity provider lands the user
inside with no visible login step.Signing out reaches the page, not the flow.
logoutHandlerredirected to
the bare sign-in URL, which with auto-redirect on is itself a redirect to the
identity provider. Our sign-out does not end the IdP session, so a user who
signed out would be signed straight back in and the button would appear to do
nothing, and the more reliable the SSO setup is, the more completely it fails.It is suppressed on a refused sign-on, and that guard is the feature. A
denial answers a redirect back to the sign-in page, so redirecting it onward
would bounce every refusal straight back to the identity provider: an infinite
loop with no surface left to read the error on. It is also suppressed by
?local=1, so a break-glass account can reach the password form when the
identity provider is the thing that is broken, without an operator editing
values and rolling out to get back in.
Changed
-
Changelog entries are now one file per pull request.
make changelog(a wrapper around changie) writes.changes/unreleased/<slug>.yaml, and the release cut folds every pending fragment intoCHANGELOG.mdunder## [Unreleased]. Before this, every open PR edited the same## [Unreleased]lines in one file: merging any one of them made the rest dirty, each rebase cost a full CI cycle of around fifty-five checks, and resolving those conflicts by keeping both sides is how the section came to hold five headings for three kinds. Two fragments are two different files and cannot conflict. EditingCHANGELOG.mdby hand still satisfies the guard. (#1200) -
The documentation version menu says which release you are reading. The
current release now appears asv0.4.7 (latest)rather thanlatest, and the
unreleased leg asdev (main, unreleased). Before this, the current release
was the ONE release whose number the menu never showed: an archived tag shows
its number only after it has been superseded, so the number a reader most
wants was the one missing. The project's own maintainer read the menu and
concludedlatestmeantmain.A new gate reconciles the menu the published site uses with the fallback a
localhugobuild uses. The two had already drifted: one listed a release the
other did not, so a local build and the published site disagreed about which
releases exist. -
The session cookie is now
Secureby default, decided by the server
rather than by the page'slocation.protocol(see the fix below).Upgrading a deployment served over plain http on a name that is not
localhost: setauth.session_cookie_insecure: trueBEFORE you upgrade. A
browser refuses aSecurecookie on such an origin, and it refuses the
Securedeletion too. So with the default, a new login is silently discarded
and sign-out stops signing anybody out: the pre-existing non-Secure
cookie from the old build stays in the jar, stays a valid session, and cannot
be cleared until its original lifetime runs out. Loopback is unaffected,
because browsers treat it as potentially trustworthy, and so is anything
behind TLS, which is every chart install.
Fixed
-
A GA release page carried none of the release. The body was generated
from the commits since the previous tag, and a GA is cut from its own release
candidate, so the only commit between the two is the promotion itself. The
v0.4.7 page said one line,release: promote v0.4.7 GA, whileCHANGELOG.md
held 35 entries for that same version: everything written for a human to read
stayed in a file, and the page most people reach from GitHub showed nothing.The body is now composed from the changelog section for the tag, so a release
page says what the release did. A candidate falls back to[Unreleased],
which is where its entries are. The commits are still one click away, as a
compare link.The generated list was also keeping noise it meant to drop: the filters were
anchored as^docs:,^test:and^chore:, and every commit in this
repository is scoped, as indocs(changelog):, so none of the three ever
matched anything. -
Building and deploying in separate steps could name the same image two
different ways (#1227). A project that setsregistry.tag_strategy: git_shahad its image pushed under the DAG version byleoflow compile --build --push, whileleoflow deploylooked for it under the commit SHA,
because the build never consulted the strategy and the deploy did.This only shows up when the two commands run separately, which is the normal
CI/CD shape: build in one job, deploy in another with--skip-build. A single
leoflow deploy, which does both, was never affected. With the default
strategy the two rules happen to agree, so the fail...
v0.4.8-rc.1
Leoflow v0.4.8-rc.1
A 0.x (pre-1.0) build — SemVer carries the maturity, there is no separate
alpha/beta, and the pre-alpha series ended at v0.0.1 (ADR 0037). APIs and
on-disk shape may still evolve between minor versions; -rc.N tags are release
candidates gated by the E2E suite. Install this exact release with:
curl -fsSL https://raw.githubusercontent.com/neochaotic/leoflow/v0.4.8-rc.1/install.sh | LEOFLOW_VERSION=v0.4.8-rc.1 shA bare
curl … | shinstalls the latest stable release (/releases/latest
excludes pre-releases), so on a pre-release page it would NOT give youv0.4.8-rc.1.
LEOFLOW_VERSIONmust sit on theshside of the pipe (notcurl) — a
VAR=x curl … | shprefix sets the var forcurlonly, soinstall.shwould
not see it and would fall back to latest-stable.
Changelog
- 578ddad: docs(changelog): merge the duplicated Unreleased sections (#1231) (@neochaotic)
- 963295d: docs(contribute): give the docs the preview command that works (#1233) (@neochaotic)
- 8b8af6b: docs(gcp): correct what warm-pool-ab can do, and name the two defects that say not yet (#1202) (@neochaotic)
- e21a382: feat(changelog): one fragment file per PR instead of one shared section (#1232) (@neochaotic)
- ae08669: feat(gcp): put the node TTL on before the pool is full, not after (#1209) (@neochaotic)
- 9333af7: feat(helm): let an operator set the UI refresh interval from the chart (#1197) (@neochaotic)
- b4b1e0d: feat(oidc): offer auto-redirect to the IdP, and read a tenant claim that is an array (#1192) (@neochaotic)
- 8309df1: fix(agent,executor): stop a task's survivors reaching the next, and describe an OOM on the recovery path (#1220) (@neochaotic)
- 5c608b5: fix(auth): set the session cookie server-side on the password login path (#1195) (@neochaotic)
- d766a7b: fix(cli): build the image with the tag strategy deploy reads, not with the version (#1228) (@neochaotic)
- a27da4f: fix(cli): say when setup will download a Python, instead of naming one it will not use (#1226) (@neochaotic)
- 35a5604: fix(cut-release): the dry run said 'changelog: unchanged' while two entries were about to move (#1235) (@neochaotic)
- d7cbfd8: fix(gcp): a gcloud wait that gave up is not a failure, and a cluster it left is not absent (#1206) (@neochaotic)
- 1390cc0: fix(gcp): check the account settings before provisioning, not one line after (#1211) (@neochaotic)
- 60c51e8: fix(gcp): measure warm pools on an interval both arms have, and report it (#1204) (@neochaotic)
- 8a29ccc: fix(gcp): never delete a cluster an earlier run recorded, and log in as an email (#1222) (@neochaotic)
- 828ec89: fix(gcp): remove a refusal whose stated reason had stopped being true (#1221) (@neochaotic)
- 4983b4a: fix(gcp): submit a level in parallel, and record the concurrency that existed (#1215) (@neochaotic)
- 1ed686c: fix(gcp): the saturation rule compared p95 against 3, not against 3x the baseline (#1208) (@neochaotic)
- 6c03e2b: fix(gcp): wait for a level's pods to be gone, instead of sleeping and hoping (#1213) (@neochaotic)
- 08a0bbc: fix(oidc): bound every call to the IdP, not just the one a context could reach (#1210) (@neochaotic)
- 85b7e90: fix(storage): stop the scheduler handing back leadership once an hour (#1205) (@neochaotic)
- b3fb4be: release: prepare v0.4.8-rc.1 (@neochaotic)
- 6abe030: test(e2e): exercise the two-step build-then-deploy path, with a non-default tag strategy (#1229) (@neochaotic)
- 5448428: test(gcp): provision and tear down a throwaway cluster for the experiments local cannot run (#1194) (@neochaotic)
- 699f6a9: test(gcp): retry a cluster that was briefly unreachable, and only that (#1223) (@neochaotic)
- 5ef246e: test(gcp): three experiment runners, and the one that could be run (#1198) (@neochaotic)
- 1957d6d: test(observability): pin that a logged claim cannot forge a log record (#1201) (@neochaotic)
- 184c8cd: test(soak): a long-running resilience battery with continuous invariants (#1183) (@neochaotic)
Artifacts are checksummed (SHA-256) and the checksums file is cosign-signed
(keyless). Verify with cosign verify-blob.
v0.4.7
Leoflow v0.4.7
A 0.x (pre-1.0) build — SemVer carries the maturity, there is no separate
alpha/beta, and the pre-alpha series ended at v0.0.1 (ADR 0037). APIs and
on-disk shape may still evolve between minor versions; -rc.N tags are release
candidates gated by the E2E suite. Install this exact release with:
curl -fsSL https://raw.githubusercontent.com/neochaotic/leoflow/v0.4.7/install.sh | LEOFLOW_VERSION=v0.4.7 shA bare
curl … | shinstalls the latest stable release (/releases/latest
excludes pre-releases), so on a pre-release page it would NOT give youv0.4.7.
LEOFLOW_VERSIONmust sit on theshside of the pipe (notcurl) — a
VAR=x curl … | shprefix sets the var forcurlonly, soinstall.shwould
not see it and would fall back to latest-stable.
Changelog
- 7fa5018: release: promote v0.4.7 GA (@neochaotic)
Artifacts are checksummed (SHA-256) and the checksums file is cosign-signed
(keyless). Verify with cosign verify-blob.
v0.4.7-rc.2
Leoflow v0.4.7-rc.2
A 0.x (pre-1.0) build — SemVer carries the maturity, there is no separate
alpha/beta, and the pre-alpha series ended at v0.0.1 (ADR 0037). APIs and
on-disk shape may still evolve between minor versions; -rc.N tags are release
candidates gated by the E2E suite. Install this exact release with:
curl -fsSL https://raw.githubusercontent.com/neochaotic/leoflow/v0.4.7-rc.2/install.sh | LEOFLOW_VERSION=v0.4.7-rc.2 shA bare
curl … | shinstalls the latest stable release (/releases/latest
excludes pre-releases), so on a pre-release page it would NOT give youv0.4.7-rc.2.
LEOFLOW_VERSIONmust sit on theshside of the pipe (notcurl) — a
VAR=x curl … | shprefix sets the var forcurlonly, soinstall.shwould
not see it and would fall back to latest-stable.
Changelog
- c5bb7e4: docs(release): add the SSO tranche to the RC cluster-validation runbook (#1174) (@neochaotic)
- 34ae395: docs(release): record the rc.2 runbook execution, and carry row 17 forward (#1178) (@neochaotic)
- 3bbebec: feat(api): offer single sign-on on the sign-in page when a flow exists (#1161) (@neochaotic)
- 80b8fd6: feat(helm): make OIDC reachable from values, so SSO can be turned on (#1159) (@neochaotic)
- 4889dd1: feat(oidc): narrow Google's account chooser to the Workspace domain, and document the whole journey (#1164) (@neochaotic)
- b17b8db: fix(api): log every SSO denial, and stop discarding the cause behind token_invalid (#1162) (@neochaotic)
- 1a13016: fix(api): populate class_ref.module_path, which was making OpenMetadata ingest nothing (#1156) (@neochaotic)
- 900e526: fix(api): return a refused single sign-on to the login page, not to raw JSON (#1169) (@neochaotic)
- b2e2737: fix(chart): let the startup gate render when upgrading from a chart that never had it (#1157) (@neochaotic)
- 1a1cdfe: fix(chart): stop delivering the control plane's credentials through a Helm hook (#1155) (@neochaotic)
- 18e1bd3: fix(config): reject a blank OIDC name at boot, and stop reporting a missing tenant as a database failure (#1172) (@neochaotic)
- 9a9431d: fix(server): name at boot the OIDC settings that point at rows which do not exist (#1168) (@neochaotic)
- 35cf7c7: fix(server): name at boot the four SSO configurations that fail at login (#1163) (@neochaotic)
- 8a0b022: fix(server): run the OIDC name check after the bootstrap admin exists (#1175) (@neochaotic)
- ec234b6: fix(server): warn when no break-glass address can actually sign in (#1173) (@neochaotic)
- c884c94: release: prepare v0.4.7-rc.2 (@neochaotic)
Artifacts are checksummed (SHA-256) and the checksums file is cosign-signed
(keyless). Verify with cosign verify-blob.
v0.4.7-rc.1
Leoflow v0.4.7-rc.1
A 0.x (pre-1.0) build — SemVer carries the maturity, there is no separate
alpha/beta, and the pre-alpha series ended at v0.0.1 (ADR 0037). APIs and
on-disk shape may still evolve between minor versions; -rc.N tags are release
candidates gated by the E2E suite. Install this exact release with:
curl -fsSL https://raw.githubusercontent.com/neochaotic/leoflow/v0.4.7-rc.1/install.sh | LEOFLOW_VERSION=v0.4.7-rc.1 shA bare
curl … | shinstalls the latest stable release (/releases/latest
excludes pre-releases), so on a pre-release page it would NOT give youv0.4.7-rc.1.
LEOFLOW_VERSIONmust sit on theshside of the pipe (notcurl) — a
VAR=x curl … | shprefix sets the var forcurlonly, soinstall.shwould
not see it and would fall back to latest-stable.
Changelog
- c5735f7: docs(adr): withdraw D9's claim about how the OIDC slice leaves are loaded (#1152) (@neochaotic)
- ca369ac: docs(config): the slices bind from env, and the chart cannot carry the two maps (#1148) (@neochaotic)
- b331561: docs(dbt): say which dbt runs the parse, because it differs by edition (#1109) (@neochaotic)
- 1010a60: docs(release): refresh §3a for the v0.4.7 tranche, and stop retiring work that was never done (#1151) (@neochaotic)
- d008827: feat(api): let clear re-run a task on the image that produced it (#1138) (@neochaotic)
- fe5c7eb: feat(cli): leoflow build — one command for a whole workspace (#1115) (#1118) (@neochaotic)
- 68f6879: feat(cli): make include_paths copy the files it says it copies (#1062) (#1113) (@neochaotic)
- 668976a: feat(lite): a way to start clean, and a banner that admits what it inherited (#1104, #1105) (#1107) (@neochaotic)
- 98e7f60: feat(lite): seed a declared connection the environment already carries (#1103) (#1108) (@neochaotic)
- 4b82344: fix(api): give clearTaskInstances the Airflow defaults, so an unflagged call cannot destroy state (#1149) (@neochaotic)
- 6d60aed: fix(api): stop reporting a database outage as the caller's fault (#1087, #1071) (#1097) (@neochaotic)
- dc96fe7: fix(chart): gate the probes on a startupProbe, so a slow boot is not a restart loop (#1150) (@neochaotic)
- 81f48bf: fix(chart): make config.cors.allowedOrigins mean something, without widening CORS on upgrade (#1147) (@neochaotic)
- 1e06711: fix(chart): the migration Job was the only workload ignoring pod placement (#1056) (#1111) (@neochaotic)
- 269db27: fix(cli): make a 401 say when the saved token belongs to another server (#1102) (#1106) (@neochaotic)
- 8cb5107: fix(cli): make the wrong-server 401 hint name a command that exists (#1123) (@neochaotic)
- 748ef13: fix(cli): say when a
!in exclude_paths was ignored (#1081) (#1110) (@neochaotic) - 9abd64a: fix(config): require the OIDC tenant pin at boot, so a login-proof deployment says so (#1146) (@neochaotic)
- aa05761: fix(dbt): a dbt-only DAG was dropping the secrets it declared (#997) (#1112) (@neochaotic)
- f8db184: fix(dbt): refuse an unusable derived task id by name, and pin id stability (#1114) (#1117) (@neochaotic)
- 112e386: fix(dbt): warn loudly when granularity=folder merges two unrelated groups (#1114) (#1116) (@neochaotic)
- 531a242: fix(dev): build each venv on the interpreter the project declares (#1092) (#1093) (@neochaotic)
- 7d18339: fix(server): bound the pod informer's warm-up so a cold cache cannot withhold the listeners (#1141) (@neochaotic)
- 5f0200e: release: prepare v0.4.7-rc.1 (@neochaotic)
- f9fc437: test(e2e): lock what the control plane says when its database dies mid-flight (#1101) (@neochaotic)
- 627c006: test(executor): stop waitForFile handing an empty file to its caller (#1120) (@neochaotic)
Artifacts are checksummed (SHA-256) and the checksums file is cosign-signed
(keyless). Verify with cosign verify-blob.
v0.4.6
Leoflow v0.4.6
A 0.x (pre-1.0) build — SemVer carries the maturity, there is no separate
alpha/beta, and the pre-alpha series ended at v0.0.1 (ADR 0037). APIs and
on-disk shape may still evolve between minor versions; -rc.N tags are release
candidates gated by the E2E suite. Install this exact release with:
curl -fsSL https://raw.githubusercontent.com/neochaotic/leoflow/v0.4.6/install.sh | LEOFLOW_VERSION=v0.4.6 shA bare
curl … | shinstalls the latest stable release (/releases/latest
excludes pre-releases), so on a pre-release page it would NOT give youv0.4.6.
LEOFLOW_VERSIONmust sit on theshside of the pipe (notcurl) — a
VAR=x curl … | shprefix sets the var forcurlonly, soinstall.shwould
not see it and would fall back to latest-stable.
Changelog
- 68e6552: release: promote v0.4.6 GA (@neochaotic)
Artifacts are checksummed (SHA-256) and the checksums file is cosign-signed
(keyless). Verify with cosign verify-blob.
v0.4.6-rc.1
Leoflow v0.4.6-rc.1
A 0.x (pre-1.0) build — SemVer carries the maturity, there is no separate
alpha/beta, and the pre-alpha series ended at v0.0.1 (ADR 0037). APIs and
on-disk shape may still evolve between minor versions; -rc.N tags are release
candidates gated by the E2E suite. Install this exact release with:
curl -fsSL https://raw.githubusercontent.com/neochaotic/leoflow/v0.4.6-rc.1/install.sh | LEOFLOW_VERSION=v0.4.6-rc.1 shA bare
curl … | shinstalls the latest stable release (/releases/latest
excludes pre-releases), so on a pre-release page it would NOT give youv0.4.6-rc.1.
LEOFLOW_VERSIONmust sit on theshside of the pipe (notcurl) — a
VAR=x curl … | shprefix sets the var forcurlonly, soinstall.shwould
not see it and would fall back to latest-stable.
Changelog
- ee64686: build(migrate): compile the migrate CLI from our go.mod instead of shipping a third-party image (#1039) (#1045) (@neochaotic)
- 12068c7: build: move the DAG task base image to Debian 13 (trixie) (#1038) (@neochaotic)
- edf5c6b: chore(deps): bump actions/checkout from 4 to 7 (#965) (@dependabot[bot])
- 9bd609a: chore(deps): bump actions/setup-python from 5 to 7 (#964) (@dependabot[bot])
- b47961c: chore(deps): bump docker/setup-qemu-action from 3.7.0 to 4.3.0 (#967) (@dependabot[bot])
- d38c69a: ci: run the readiness-budget and Hugo gates per PR, not only at the release cut (#1057) (@neochaotic)
- 8c71818: ci: scan container images for CVEs, with a policy that can stay on (#1034) (@neochaotic)
- b2929f1: feat(runtime): publish a py3.13 task base, deprecate py3.10, and make the published-Python list singular (#1037) (@neochaotic)
- 80411e5: fix(agent): make execution_timeout kill the task's process group (#1074) (@neochaotic)
- bc386ac: fix(agentrpc): stop database errors reaching the task pod, keep them in the log (#1077) (@neochaotic)
- c54df03: fix(api): give readiness its own connection and one budget, and floor the chart timeout (#1046) (@neochaotic)
- b2afbb3: fix(api): make /readyz assert the schema invariant boot asserts, on every probe (#1023) (#1033) (@neochaotic)
- 5aa800a: fix(api): stop database errors reaching tenants, keep them in the log (#1069) (@neochaotic)
- 70794e0: fix(chart): mount the database CA into the migration Job, and stop it being BestEffort (#1054) (@neochaotic)
- 6bd3213: fix(cli): make exclude_paths reach the image build, and stop baking dbt's host artifacts (#1059) (@neochaotic)
- 57b812e: fix(cli): shell-quote dependency and system-package specs in the generated Dockerfile (#1066) (@neochaotic)
- fbb97c6: fix(helm): keep the migration hook's pod out of the control-plane selector (#1075) (@neochaotic)
- b248375: fix(helm): refuse an allowMetadataEgress entry wider than one host (#1065) (@neochaotic)
- 6fe6d5a: fix(helm): refuse an inverted autoscaling range, and stop the NetworkPolicy hiding the metrics port (#1073) (@neochaotic)
- a2370f3: release: prepare v0.4.6-rc.1 (@neochaotic)
- cc1a73d: test(cli): pin both branches of the DAG base-image choice against a stamped binary (#1035) (@neochaotic)
Artifacts are checksummed (SHA-256) and the checksums file is cosign-signed
(keyless). Verify with cosign verify-blob.
v0.4.5
Leoflow v0.4.5
A 0.x (pre-1.0) build — SemVer carries the maturity, there is no separate
alpha/beta, and the pre-alpha series ended at v0.0.1 (ADR 0037). APIs and
on-disk shape may still evolve between minor versions; -rc.N tags are release
candidates gated by the E2E suite. Install this exact release with:
curl -fsSL https://raw.githubusercontent.com/neochaotic/leoflow/v0.4.5/install.sh | LEOFLOW_VERSION=v0.4.5 shA bare
curl … | shinstalls the latest stable release (/releases/latest
excludes pre-releases), so on a pre-release page it would NOT give youv0.4.5.
LEOFLOW_VERSIONmust sit on theshside of the pipe (notcurl) — a
VAR=x curl … | shprefix sets the var forcurlonly, soinstall.shwould
not see it and would fall back to latest-stable.
Changelog
- d8a5042: release: promote v0.4.5 GA (@neochaotic)
Artifacts are checksummed (SHA-256) and the checksums file is cosign-signed
(keyless). Verify with cosign verify-blob.