GitHub Actions for Kestra – CI/CD Workflow Examples icon GitHub Actions for Kestra – CI/CD Workflow Examples

Use GitHub Actions to automate the validation and deployment of your Kestra flows and namespace files.

Automate Kestra deployments with GitHub Actions

Kestra provides three official GitHub Actions enabling you to build robust CI/CD pipelines in your GitHub repository:

  • Validate your flows
  • Deploy your flows
  • Deploy namespace files

To use these Actions, your Kestra instance must be reachable by the GitHub Actions runner—either publicly or via a self-hosted runner. If you need to validate flows offline — without connecting to a running Kestra instance — use the legacy marketplace action instead: kestra-validate-action.


Official Kestra Actions

Kestra provides these three Actions for CI/CD pipelines:


Input reference

Validate Flows Action inputs

InputRequiredDefaultDescription
directory'./'Folder containing your flows (YAMLs).
serverURL of your Kestra server.
apiTokenAPI Token for authentication (Enterprise Edition only).
userBasic auth username.
passwordBasic auth password.
tenant"main"Tenant identifier (Enterprise Edition only, for multi-tenancy).

(See action.yml)


Deploy Flows Action inputs

InputRequiredDefaultDescription
directory'./'Folder containing your flows (YAMLs).
namespaceNamespace to deploy flows to (optional). If omitted, each flow uses the namespace defined in its YAML.
override'false'If true, override existing flows.
serverURL of your Kestra server.
apiTokenAPI Token for authentication (EE only).
userBasic auth username.
passwordBasic auth password.
tenant"main"Tenant identifier (Enterprise Edition only, for multi-tenancy).

(See action.yml)


Deploy Namespace Files Action inputs

InputRequiredDefaultDescription
localPath'./'Path to your local file or directory for upload.
namespacePathRemote namespace path to deploy files to (if uploading a file, must match a file path).
namespaceNamespace to deploy files to.
override'false'If true, override existing files.
serverURL of your Kestra server.
apiTokenAPI Token for authentication (EE only).
userBasic auth username.
passwordBasic auth password.
tenant"main"Tenant identifier (Enterprise Edition only, for multi-tenancy).

(See action.yml)


Example workflow

A sample CI/CD workflow that validates and deploys flows with the new Kestra Actions:

name: Kestra CI/CD
on: [push]
jobs:
validate:
runs-on: ubuntu-latest
steps:
- name: Checkout repository content
uses: actions/checkout@v4
- name: Validate flows
uses: kestra-io/github-actions/validate-flows@main
with:
directory: ./kestra/flows
server: ${{ secrets.KESTRA_HOSTNAME }}
# Optional: uncomment for Enterprise Edition
# apiToken: ${{ secrets.KESTRA_API_TOKEN }}
deploy:
runs-on: ubuntu-latest
needs: validate
steps:
- name: Checkout repository content
uses: actions/checkout@v4
- name: Deploy product flows
uses: kestra-io/github-actions/deploy-flows@main
with:
directory: ./kestra/flows/product
namespace: product
server: ${{ secrets.KESTRA_HOSTNAME }}
- name: Deploy engineering flows
uses: kestra-io/github-actions/deploy-flows@main
with:
directory: ./kestra/flows/engineering
namespace: engineering
server: ${{ secrets.KESTRA_HOSTNAME }}
# Example: Deploy namespace files
upload_nsfiles:
runs-on: ubuntu-latest
steps:
- name: Checkout repository content
uses: actions/checkout@v4
- name: Upload config YAML to engineering namespace
uses: kestra-io/github-actions/deploy-namespace-files@main
with:
localPath: ./config/eng.yaml
namespace: engineering
namespacePath: config/eng.yaml
server: ${{ secrets.KESTRA_HOSTNAME }}

Deploy to multiple namespaces

You can target multiple namespaces in one workflow either by:

  • Letting each flow keep its own namespace value (omit the namespace input).
  • Running the action multiple times with different namespace inputs.
name: Kestra Deploy Across Namespaces
on: [push, workflow_dispatch]
jobs:
deploy-default-namespaces:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: kestra-io/github-actions/deploy-flows@main
with:
server: https://kafka-ee.preview.dev.kestra.io
apiToken: ${{ secrets.KESTRA_API_TOKEN }}
tenant: my-tenant
directory: ./flows # Flows keep their own namespace values
override: true
deploy-to-other-namespace:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: kestra-io/github-actions/deploy-flows@main
with:
server: https://kafka-ee.preview.dev.kestra.io
apiToken: ${{ secrets.KESTRA_API_TOKEN }}
tenant: my-tenant
directory: ./flows
namespace: company.team # Force all flows to this namespace
override: true

The same pattern applies to namespace files: run deploy-namespace-files once per target namespace, or keep authorship paths by omitting overriding namespacePath.

Examples by use case

Validate flows (single file or folder)

jobs:
validate-single-flow:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: kestra-io/github-actions/validate-flows@main
with:
server: ${{ secrets.KESTRA_HOSTNAME }}
apiToken: ${{ secrets.KESTRA_API_TOKEN }}
tenant: my-tenant
directory: ./flows/my-log-flow.yml # Single file
validate-folder:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: kestra-io/github-actions/validate-flows@main
with:
server: ${{ secrets.KESTRA_HOSTNAME }}
apiToken: ${{ secrets.KESTRA_API_TOKEN }}
tenant: my-tenant
directory: ./flows # Folder path of files

Deploy flows (use authored namespaces vs override)

jobs:
deploy-authored-namespaces:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: kestra-io/github-actions/deploy-flows@main
with:
server: ${{ secrets.KESTRA_HOSTNAME }}
apiToken: ${{ secrets.KESTRA_API_TOKEN }}
tenant: my-tenant
directory: ./flows # Each flow keeps its namespace
override: true
deploy-to-specific-namespace:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: kestra-io/github-actions/deploy-flows@main
with:
server: ${{ secrets.KESTRA_HOSTNAME }}
apiToken: ${{ secrets.KESTRA_API_TOKEN }}
tenant: my-tenant
directory: ./flows
namespace: company.team # Force all flows to a specific namespace
override: true

Deploy namespace files (single file, folder, folder to custom path)

jobs:
upload-single-file:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: kestra-io/github-actions/deploy-namespace-files@main
with:
server: ${{ secrets.KESTRA_HOSTNAME }}
apiToken: ${{ secrets.KESTRA_API_TOKEN }}
tenant: my-tenant
localPath: ./nsfiles/file1.txt
namespacePath: single/file1.txt
namespace: my-namespace
override: true
upload-folder:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: kestra-io/github-actions/deploy-namespace-files@main
with:
server: ${{ secrets.KESTRA_HOSTNAME }}
apiToken: ${{ secrets.KESTRA_API_TOKEN }}
tenant: my-tenant
localPath: ./nsfiles # Upload entire folder
namespacePath: ./nsfiles
namespace: my-namespace
override: true
upload-folder-to-custom-path:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: kestra-io/github-actions/deploy-namespace-files@main
with:
server: ${{ secrets.KESTRA_HOSTNAME }}
apiToken: ${{ secrets.KESTRA_API_TOKEN }}
tenant: my-tenant
localPath: ./nsfiles
namespacePath: myFiles # Remap destination path
namespace: my-namespace
override: true

Additional resources

Was this page helpful?