Skip to content

Releases: Nonetss/playbook-runner

v0.11.4 — long-running tasks keep their stream alive

Choose a tag to compare

@Nonetss Nonetss released this 07 Oct 11:58

Highlights

Long-running tasks no longer drop their stream

Runs with a task that stays silent for minutes, such as apt upgrade, dnf update or a slow script, could end as failed with gRPC INTERNAL: Received RST_STREAM with code 2 (Internal server error), even well within the one-hour run limit. Ansible only reports when a task starts or ends, so the backend → gateway → Ansible stream carried no traffic in between, and it was reset.

  • Heartbeats. While a run produces no events, the Ansible service sends a small heartbeat frame every 15 seconds. This also covers the Git fetch before the run. The backend discards these frames: they never reach the browser, the live run view or the stored job run events.
  • HTTP/2 keepalive on both ends, so a dead connection is detected in seconds instead of at the run deadline.
  • Clearer error when a stream is lost anyway. For example, the gateway may restart mid-run. The run now says that the connection to the Ansible service was lost and that the execution may have continued or finished on the hosts, instead of showing a bare gRPC INTERNAL. Interactive runs get it as a 502.

Upgrade notes

Pull the new images and restart. Update the backend and Ansible images together, because the gRPC contract changed on both sides:

docker compose pull && docker compose up -d

No compose changes and no database migration in this release. A new optional variable, RUN_HEARTBEAT_INTERVAL_S on the Ansible service (default 15), tunes the heartbeat interval.

Other changes since v0.11.0

  • Built-in "All" inventory group (v0.11.3): it always contains every device and is resolved at run time. Runs, commands, scripts and scheduled jobs can target the whole fleet and pick up devices added later. It is pinned first in Groups (read-only, with its own detail page), in the inventory pickers and in ⌘K search. The group name all (any case) is now reserved.
  • Run history loads with infinite scroll instead of a "Load more" button (v0.11.1).
  • Section sidebar: the collapse control is a full-width "Collapse menu" / "Expand menu" row (v0.11.1).
  • Fixes:
    • On phones, the command palette is anchored to the top so the keyboard no longer covers it.
    • The page hero keeps its icon on the title's line.
    • The active navbar section stays highlighted after picking a menu link.
  • Tests:
    • API unit tests moved to packages/api/tests and the Playwright suite to apps/frontend/tests/e2e.
    • New end-to-end coverage for the All group.
  • Docs, AGENTS.md and OpenSpec specs updated.

v0.11.0 — navbar search & API keys entry

Choose a tag to compare

@Nonetss Nonetss released this 04 Oct 15:57

Highlights

Navbar search

Press ⌘K (macOS) or Ctrl+K anywhere in the app, or use the search field next to the account button, to jump to any page without opening the section menus.

  • Every page is listed, grouped like the navigation: a General group, then Inventario, Ansible and Bash.
  • Records too. Once you type, it lists your playbooks, scripts, scheduled jobs and inventory groups, and opens their edit or detail page. Typing a section name, such as "playbooks", lists all of that section's records. The records come from the same lists the pages already load, so they cost no extra requests once cached.
  • Forgiving matching. It ignores case and accents, and every word must match: "ansible historial" finds the run history.
  • Recent pages. With an empty query, your last five pages are suggested first. They are stored per user in the browser.
  • The search follows the interface language. On small screens it is an icon button next to the account menu.

Navbar layout

  • On desktop, the sections now sit on the left, right after the brand and a thin separator. The actions (language, theme, search and account) sit on the right.
  • Settings is now the "API keys" entry in the navbar and the mobile menu, since the page only holds API keys. The gear button is gone. The URL is still /config.

Upgrade notes

Pull the new images and restart:

docker compose pull && docker compose up -d

No new environment variables, no compose changes and no database migration in this release.

Other changes since v0.10.0

  • SSO: the sign-in page shows the SSO button only when the backend has SSO configured. A new public auth-config endpoint tells it whether SSO is on.
  • Project website at https://nonetss.github.io/playbook-runner/: a guided tour of the app and bilingual docs (English and Spanish), published by GitHub Pages. It includes a full-screen screenshot viewer, copy buttons on code blocks and an architecture diagram with the gateway routing table.
  • Tests and CI: unit tests for the API (bun test) and the Ansible service (pytest), plus Playwright coverage for the navbar search. Lint, type checks and unit tests run on every pull request, and the GitHub Actions are on their Node 24 releases.
  • Frontend: link prefetching moved off the prefetchQuery API, which is deprecated in TanStack Query 5.104.
  • README, AGENTS.md and OpenSpec specs updated.

v0.10.0 — standalone gateway & Docker dev environment

Choose a tag to compare

@Nonetss Nonetss released this 04 Oct 09:29

⚠️ Deployment change. The frontend image no longer publishes the site: a new gateway image does. Refresh your compose.yml before pulling — if you track latest with the old compose file, the site stops answering after a pull. See Upgrade notes.

Highlights

Standalone gateway

Caddy moved out of the frontend image into its own playbook-runner-gateway image, the only place that decides which app serves each request:

  • Public HTTP entry point — the only published port. /rpc, /api, /scalar and /openapi.json go to the backend; everything else goes to the frontend, so the browser still sees a single origin.
  • Internal gRPC router on :50050 (never published). The backend reaches the Ansible service through it; calls are routed by proto package (run.* → Ansible), events stream through one by one, and cancelling a run still stops Ansible on the runner. Unknown services answer UNIMPLEMENTED.
  • The frontend image now runs only Astro SSR on :4321, reachable only inside the Docker network.

Docker dev environment

bun run dev now builds and starts the whole stack in Docker with hot reload — frontend, backend, Ansible service and gateway — using docker compose watch (no bind mounts) on the host network, so every service keeps the same localhost ports as native development. The gateway's production-like site is on http://localhost:8080.

  • bun run dev:down removes the dev containers.
  • The native Turbo workflow is now bun run dev:local; pair it with bun run gateway to run only the gateway.
  • PostgreSQL is not included: point DATABASE_URL at your own.

Upgrade notes

  1. Refresh the compose file, then pull and restart:

    curl -fsSL https://raw.githubusercontent.com/Nonetss/playbook-runner/v0.10.0/compose.prod.yml -o compose.yml
    docker compose pull && docker compose up -d
  2. No new required variables. The gateway is published on GATEWAY_PORT and falls back to your existing FRONTEND_PORT, so the public port does not change. Optionally rename FRONTEND_PORT → GATEWAY_PORT in .env.

  3. ANSIBLE_GRPC_TARGET now defaults to localhost:50050 (the gateway); the compose files set gateway:50050. If you run the apps natively without the gateway, set ANSIBLE_GRPC_TARGET=localhost:50051 in apps/backend/.env.

No database migration in this release.

New optional environment variables

Variable Default Purpose
GATEWAY_PORT FRONTEND_PORT, else 4321 Host port the gateway is published on
GATEWAY_IMAGE_TAG latest Gateway image tag in compose.prod.yml

Other changes

  • CI builds and publishes the gateway image (amd64 + arm64).
  • Frontend and gateway healthchecks; the backend waits for the gateway.
  • scripts/bootstrap.sh writes GATEWAY_PORT and GATEWAY_IMAGE_TAG.
  • Fixed a syntax error in the cron schedule builder.
  • README, AGENTS.md, architecture diagram and OpenSpec specs updated.

v0.9.1 — typography system, job run pagination & UI polish

Choose a tag to compare

@Nonetss Nonetss released this 29 Sep 11:55

Highlights

Job run history pagination

jobs.runs.list (/api/v1/jobs/runs/list) accepts optional limit (1–100) and offset parameters. Omitting both still returns every run, so existing API clients keep working. The job detail page now loads its run history in pages as you scroll instead of fetching every run at once.

Searchable playbook picker in the job form

The job form uses the same searchable playbook picker as the run switcher, which makes it easier to pick a playbook in large catalogues.

Typography system rollout

The typography system gained new roles and utilities, and it is now applied across shared components, navigation, auth, dashboard, jobs, playbooks and run screens. Technical inputs use the data typeface consistently.

Other changes

  • New TerminalPanel component shared by the run consoles.
  • Consistent focus-ring keyboard focus styling across shared, app-shell and feature components.
  • Accessibility: aria labels for extra-variable inputs and better command-input labelling.
  • Better responsive wrapping; more compact script form (the language hint now sits next to the content label).
  • README updated for Git repository integration and upgrade instructions.

No new environment variables, database migrations or proto changes in this release.

v0.9.0 — Git repositories as a playbook source

Choose a tag to compare

@Nonetss Nonetss released this 29 Sep 10:57

Upgrading from v0.7.x? v0.8.0 added the required CREDENTIALS_ENCRYPTION_KEY environment variable. See the v0.8.0 upgrade notes before deploying.

Highlights

Git repositories as a playbook source

Prefer to keep your playbooks in Git instead of the browser? Register a repository from the Playbooks page and press Sync:

  • Public HTTPS repositories, or private over SSH using one of your stored credentials as a deploy key.
  • Pick a branch — the form lists the remote's branches and preselects the default one — and optionally a subdirectory to scan.
  • Every playbook file on the branch shows up as a read-only playbook you can run and schedule. New repositories sync automatically when you save them.
  • Runs execute from a checkout of the synced commit, so roles, templates, group_vars and files/ next to the playbook just work. The repository's ansible.cfg is ignored.
  • Job runs record the commit they ran at, shown in the job's run history.
  • Copy to Playbook Runner turns a Git playbook into a regular, editable one (only that file is copied).
  • Files removed upstream disappear on the next sync; they are only kept (hidden) while a job still uses them, so that job fails with a clear message.

Not supported yet: webhooks/auto-sync, HTTPS token auth and installing Galaxy requirements.yml.

Collapsible sections

Folders and repositories in the playbooks browser can be collapsed; the state is remembered per browser.

Upgrade notes

  • Database migration — adds playbook_repositories and new columns on playbooks and job_runs. The backend applies it on startup; no manual step.
  • Update the backend and Ansible images together — the gRPC contract gained SyncRepository, ListBranches and DeleteRepository, and the Ansible image now ships git.
  • Repository mirrors are stored in the Ansible state volume (STATE_DIR/repos).

New optional environment variables (Ansible service)

Variable Default Purpose
GIT_TIMEOUT_S 120 Timeout per git command
GIT_MAX_REPO_MB 512 Maximum size of a repository mirror
MAX_CONCURRENT_SYNCS 2 Concurrent repository syncs

Other changes

  • README, AGENTS.md and OpenSpec specs updated.
  • Refreshed playbooks and cron screenshots.

v0.8.2 — installable PWA & layout polish

Choose a tag to compare

@Nonetss Nonetss released this 29 Sep 10:19

Upgrading from v0.7.x? v0.8.0 added the required CREDENTIALS_ENCRYPTION_KEY environment variable. See the v0.8.0 upgrade notes before deploying.

Highlights

Installable PWA

The frontend can now be installed on mobile: web manifest, theme colour, apple-touch-icon, generated icons, and a network-first service worker that never caches /rpc, /api, /scalar or /openapi.json.

Layout polish

Feature components, forms and UI utilities were aligned for a consistent geometric layout. The dashboard and config pages gained responsive grids (including the API key cards).

Other changes

  • Translations and design documentation updated.

No new environment variables in this release.

v0.8.1 — frontend design system overhaul

Choose a tag to compare

@Nonetss Nonetss released this 29 Sep 10:19

Highlights

Frontend design system

The whole frontend was rebuilt on a documented design system (apps/frontend/DESIGN.md): one terracotta accent, hierarchy through type, flat surfaces with hairlines, status shown as dot + word, and Space Grotesk / Space Mono typography.

Redesigned pages

Admin, app shell navigation, auth, config, credentials, commands, dashboard, history, inventory, jobs, playbooks, scripts, run and profile were all redesigned on the new shared primitives.

Shared components & resource framework

New shared components (MetadataCell, InlineAlert, QueryState, FieldLabel, SegmentedPicker, DetailFrame, navigation menu, checkbox, table, tabs, textarea) and a definition-driven resource framework (EntityCardGrid/EntityList, ResourceOverview, per-feature definitions). Deprecated card/list components were removed.

Navigation & layouts

A persistent section sidebar, scroll restoration, a scroll-to-top button and reworked layouts and page routes. The run console uses the refreshed terminal frame.

Other changes

  • API: credential endpoints relaxed from admin-only to any authenticated user; job metrics use proper SQL aliases.
  • i18n translations updated for the redesigned UI.
  • E2E tests updated for the new component structure.
  • OpenSpec design-system specifications applied and archived.

No new environment variables in this release.

v0.8.0 — admin & RBAC, encrypted credentials, API restructuring

Choose a tag to compare

@Nonetss Nonetss released this 29 Sep 10:19

⚠️ Upgrade notes — new required environment variable

The backend now refuses to start without CREDENTIALS_ENCRYPTION_KEY, the AES-256-GCM key used to encrypt SSH private keys at rest (base64 of exactly 32 bytes).

openssl rand -base64 32
  1. Add CREDENTIALS_ENCRYPTION_KEY=<value> to the backend environment (apps/backend/.env locally, the backend service in compose).
  2. Back the key up like BETTER_AUTH_SECRET: losing it makes every stored private key unrecoverable.
  3. Coming from v0.7.x, credentials stored in plaintext must be encrypted once:
    • local: bun run --filter backend credentials:encrypt
    • Docker: docker compose exec backend bun dist/encrypt-credentials.mjs (--decrypt rolls back)

Other deployment changes:

  • The Ansible service keeps its persistent state (SSH known_hosts) in the new ansible_state volume at /app/state; the old ./.data/ansible-runner:/app/playbook mount and ANSIBLE_PLAYBOOK_PATH are gone.
  • The backend no longer runs a gRPC server (BACKEND_GRPC_TARGET / port 50052 removed).
  • The Ansible service no longer publishes port 8000 on the host; add -f compose.debug.yml when you need it.
  • SSH host keys are verified according to SSH_HOST_KEY_POLICY (accept-new by default, strict, off). Optional.

Highlights

Admin & role-based access control

New admin dashboard with user management and role assignment. Procedures are gated by role, and users in the pending role can no longer reach protected endpoints until an admin approves them.

Encrypted credentials

SSH private keys are encrypted at rest with AES-256-GCM (v1: prefix), are never returned by the API, and are decrypted only when a run is built.

API restructuring

The run, credentials, inventory, jobs, playbooks, scripts and health endpoints were reorganised into per-feature modules with dedicated input/output schemas, central schema definitions and shared scheduling/execution utilities.

Ansible runner hardening

New SSH host-key policy module, cleaner event handling and a leaner gRPC surface (the gRPC demo was removed).

Other changes

  • Auth: dedicated hooks and an improved sign-in flow; generic OAuth stays optional.
  • Frontend: improvements across inventory, jobs, playbooks, scripts, credentials and config; extra actions on ResourcePage; redesigned job form.
  • Docker: smaller images (oven/bun:1.3.14-slim backend runtime), healthchecks that also probe gRPC :50051, and compose.debug.yml.
  • Build: tsdown with deps.alwaysBundle, so the production image ships only dist/; per-package TypeScript configuration.
  • Dependencies updated (oRPC, Hono, TypeScript, Pino, …).
  • i18n (English/Spanish), README architecture section and AGENTS documentation updated; OpenSpec changes archived.

v0.7.1 — i18n, resource hooks & safer run consoles

Choose a tag to compare

@Nonetss Nonetss released this 10 Aug 10:40

Highlights

Internationalization across the product surface

Modals, dialogs, forms, page chrome, and run consoles now pull copy through translation hooks instead of hard-coded strings. English and Spanish locale files were expanded in step, so labels, confirmations, empty states, and error messages stay consistent as new UI is added. Navbar overflow menus and the API key card actions menu were also tightened for accessibility and clearer context (e.g. action labels that include the resource name).

Standardised resource data hooks

Every major resource type — API keys, credentials, device groups, devices, groups, jobs, playbooks, and scripts — now has a dedicated feature hook built on useHydratedQuery and TanStack Query mutations. Hooks follow a uniform kebab-case file naming convention, include optimistic updates where it improves responsiveness, and integrate translation for user-facing feedback. Feature code no longer scatters raw oRPC calls and cache invalidation logic across page components.

Safer, more predictable run consoles

Starting a run from commands, playbooks, scripts, or jobs now opens a confirmation step that summarises targets, forks, sudo state, and extra variables before anything is sent to the runner. While a stream is active, a shared stop-watching control lets you detach from the live feed without cancelling the underlying job, and the playbook run modal warns when closing mid-run. Live-run lifecycle is centralised behind a shared stream hook with generation-based detachment, so ping, playbook, script, command, and job watchers all behave the same way.

Shared resource card & inventory picker

Resource cards across credentials, devices, groups, playbooks, scripts, and related listings now share a single card shell component, and run surfaces (commands, playbooks, scripts, jobs) share one inventory selection picker. Named product typography utilities (type-page-title, type-section-heading, etc.) replace ad-hoc heading classes so hierarchy stays consistent page to page.

Run status visuals & shared stream banner

Status components gained a terminal variant tuned for console-adjacent phases, giving live-run feedback a distinct look from generic badges. The run-stream status banner is reused across ping and job detail consoles so watching, stopping, and error states read the same everywhere.

Other changes

  • Refine inventory and jobs section routing so /inventory and /jobs act as proper section entry points with dedicated sub-routes and legacy redirects preserved.
  • Rework the job form around the Job type, native <select> controls, and explicit null handling for optional fields.
  • Consolidate job feature imports behind a barrel index and remove unused diagnostics components (ApiStatus, DashboardContent).
  • Add a useIsMobile hook for viewport-aware layout decisions.
  • Improve layout and styling consistency across dashboard, profile, commands, history, playbook, and script pages (padding, height calculations, viewport meta).
  • Route device and script icons through the semantic icon registry (device, fileCode).
  • Document the shared resource card shell and inventory picker under docs/design/.

v0.7.0 — shared UI patterns, section navigation & cron builder fix

Choose a tag to compare

@Nonetss Nonetss released this 10 Aug 08:50

Highlights

Frontend consolidation around shared UI primitives

Resource pages, lists, dialogs, and the navbar were each re-implementing the same interaction decisions. This release introduces shared data-display, form, and layout primitives (plus the small shadcn primitives they need) and reworks every resource surface to use them. Result: more coherent visual language, less duplication, and a single place to evolve interaction behaviour.

Section landings & split routes for Inventory and Jobs

The Inventory root used to be a tabbed page that jumped straight to Devices, and Jobs opened the scheduler directly while run history lived on a separate top-level route. /inventory and /jobs are now proper section landings with a reusable WithSidebar layout, and each gets dedicated sub-routes:

  • Inventory → /inventory/credentials, /inventory/devices, and /inventory/groups (with /inventory kept as a section overview and legacy /credentials redirecting to its canonical home).
  • Jobs → /jobs/scheduler and /jobs/history (with the legacy /history route redirecting to its canonical home).

Site navigation is now metadata-driven with localized labels, icons, descriptions, nested sub-items, and a dropdown for sections with related routes.

Graphical cron builder fixed

The cron schedule dialog would silently reset its schedule mode whenever you edited a minute/hour or weekday field, which made it feel broken when tweaking an existing schedule. Editing time fields now leaves the frequency choice stable, and the hour/minute and weekday controls are now dedicated NumberStepper and SegmentedPicker primitives — building a schedule visually behaves predictably.

Run consoles get jump-to-latest

All run consoles (playbook, command, script, and job detail) share a new jump-to-latest control with sticky-tail scroll behaviour, so following a live run no longer requires manual scrolling.

Backend ↔ runner service: response types & event handling

The gRPC runner service got updated response types and a refactor of its event handling across the Python service, the generated TypeScript stubs, and the run.proto contract.

Other changes

  • Centralise every lucide icon behind a semantic registry keyed by intent (actions, controls, resources, status, scheduling, …) so feature code depends on names, not on a particular icon library.
  • Nest Credentials under Inventory navigation and route it through the shared primitives.
  • Use semantic colours for play recap outcomes and tidy run-status metadata formatting.
  • Ignore .agents/ and .claude/ directories and configure VS Code to format proto files via the .codex tooling.