An open API service indexing awesome lists of open source software.

https://github.com/orkspace/orkestra-action

The official GitHub Action for Orkestra — runs the full ork CLI surface from any workflow
https://github.com/orkspace/orkestra-action

automation ci cicd github-action gitops kubernetes operators ork orkestra rbac

Last synced: 13 days ago
JSON representation

The official GitHub Action for Orkestra — runs the full ork CLI surface from any workflow

Awesome Lists containing this project

README

          

# Orkestra GitHub Action


Orkestra Logo

The official GitHub Action for Orkestra — runs the full `ork` CLI surface from any workflow.

---

## How it works

1. Installs the `ork` CLI (pinned or latest)
2. Runs only the commands you enable — everything else is skipped
3. Exposes file paths as outputs for steps that produce artifacts

Steps run in this order: **validate → simulate → plan → template → generate → e2e → registry**

---

## Quick start

```yaml
- uses: orkspace/orkestra-action@v1
with:
validate: "true"
simulate: "true"
e2e: "true"
```

All three commands auto-detect their files (`katalog.yaml`, `simulate.yaml`, `e2e.yaml`) from `working-directory`.

---

## Inputs

### Common

| Input | Default | Description |
|-------|---------|-------------|
| `ork-version` | `latest` | Version of the `ork` CLI to install |
| `working-directory` | `.` | Directory to run all commands in |

### `validate`

| Input | Default | Description |
|-------|---------|-------------|
| `validate` | `""` | `'true'` = auto-detect. Path = validate that file. Empty = skip. |
| `validate-depth` | `single` | `full` → `ork validate --full` (RBAC, dependency graph, per-CRD permissions) |

### `simulate`

Runs `ork simulate` — no cluster required. Reads `simulate.yaml` (assert mode) or `e2e.yaml`/`katalog.yaml` (op-print mode).

> `simulate` in CI fails on cycle errors and on `expect:` assertion failures. For full value, commit a `simulate.yaml` with assertions alongside your katalog. Generate one with `ork simulate init`.

| Input | Default | Description |
|-------|---------|-------------|
| `simulate` | `""` | `'true'` = auto-detect. Path = use that file. Empty = skip. |
| `simulate-depth` | `single` | `full` → `ork simulate ./...` (discovers all simulate.yaml + e2e.yaml recursively) |
| `simulate-katalog` | `""` | Explicit `katalog.yaml` path. Always wins over `simulate` and `simulate-depth`. |
| `simulate-cr` | `""` | Explicit `cr.yaml` path. Paired with `simulate-katalog`. Falls back to `cr.yaml` in cwd if omitted. |
| `simulate-crd` | `""` | CRD name to target when the katalog defines multiple. All CRDs if omitted. |
| `simulate-cycles` | `""` | Maximum reconcile cycles (`ork simulate --cycles`). |
| `simulate-skip-external` | `true` | Stub `external:` HTTP calls — no real network. Default `true` since CI has no dev server. |
| `simulate-skip` | `""` | Comma-separated path patterns to skip in `./...` discovery. |
| `simulate-debug` | `false` | Save per-cycle op trace to `simulate-debug-output` (`ork simulate --debug-ops`). |
| `simulate-debug-output` | `simulate-debug.txt` | File to write the `--debug-ops` trace to. |

### `plan`

| Input | Default | Description |
|-------|---------|-------------|
| `plan` | `""` | Path to `katalog.yaml` to diff against the deployed Katalog. Empty = skip. |
| `plan-bundle` | `""` | Path to a `bundle.yaml` — reads the deployed Katalog from it. No cluster access needed. |
| `plan-cm` | `""` | Path to a `configmap.yaml` — reads the deployed Katalog from it. No cluster access needed. |
| `plan-namespace` | `orkestra-system` | Namespace — only used when neither `plan-bundle` nor `plan-cm` is set. |
| `plan-output` | `plan.txt` | File to write the plan diff output to. |
| `comment-on-pr` | `""` | Set to `"true"` to post the plan diff as a PR comment. Requires `pull-requests: write` on the job. |
| `github-token` | `${{ github.token }}` | Token used to post the PR comment. Only used when `comment-on-pr` is set. |

One of `plan-bundle` or `plan-cm` is required when `plan` is set.

### `template`

| Input | Default | Description |
|-------|---------|-------------|
| `template` | `""` | Path to `katalog.yaml` to render the fully-expanded runtime Katalog. Empty = skip. |
| `template-yaml-output` | `template.yaml` | Output file for the YAML render (`ork template --yaml`). |
| `template-json-output` | `template.json` | Output file for the JSON render (`ork template --json`). |

### `generate bundle`

| Input | Default | Description |
|-------|---------|-------------|
| `generate-bundle` | `""` | Path to `katalog.yaml`. Empty = skip. |
| `generate-bundle-output` | `bundle.yaml` | Output file path |
| `generate-bundle-namespace` | `orkestra-system` | Kubernetes namespace |

### `generate configmap`

| Input | Default | Description |
|-------|---------|-------------|
| `generate-configmap` | `""` | Path to `katalog.yaml` or `komposer.yaml`. Empty = skip. |
| `generate-configmap-output` | `configmap.yaml` | Output file path |
| `generate-configmap-namespace` | `orkestra-system` | Kubernetes namespace |

### `generate rbac`

| Input | Default | Description |
|-------|---------|-------------|
| `generate-rbac` | `""` | Path to `katalog.yaml`. Empty = skip. |
| `generate-rbac-output` | `rbac.yaml` | Output file path |
| `generate-rbac-namespace` | `orkestra-system` | Namespace for the ServiceAccount |

### `generate registry` (typed operators)

| Input | Default | Description |
|-------|---------|-------------|
| `generate-registry` | `""` | Comma-separated project directories. Writes `zz_generated_runtime_registry.go` in each. Empty = skip. |

### `e2e`

| Input | Default | Description |
|-------|---------|-------------|
| `e2e` | `""` | `'true'` = auto-detect `e2e.yaml`. Path = use that file. Empty = skip. |
| `e2e-depth` | `single` | `full` → `ork e2e ./...` (discovers all e2e.yaml files recursively) |
| `e2e-keep-cluster` | `false` | Keep the kind cluster after the test (useful for debugging) |
| `e2e-cluster` | `""` | Use an existing kubectl context instead of creating a cluster |
| `e2e-wait` | `3s` | Wait between tests in `./...` discovery mode. Lets clusters fully tear down. |
| `e2e-skip` | `""` | Comma-separated path patterns to skip in `./...` discovery. |

### `registry push`

| Input | Default | Description |
|-------|---------|-------------|
| `registry-push` | `""` | `"name:version /path/to/dir"` or `"/path/to/dir"`. Empty = skip. |
| `registry-push-force` | `false` | Push even if e2e fails or metadata version differs |
| `registry-push-no-e2e` | `false` | Skip the e2e gate (even if `e2e.yaml` is present) |
| `registry-url` | `""` | OCI registry URL. Also read from `ORK_REGISTRY` env var. |
| `registry-username` | `""` | Registry username |
| `registry-password` | `""` | Registry password or token |

### `registry pull`

| Input | Default | Description |
|-------|---------|-------------|
| `registry-pull` | `""` | `"name:version"`. Empty = skip. |
| `registry-pull-out` | `""` | Directory to extract the pulled pattern into |

---

## Outputs

| Output | Description |
|--------|-------------|
| `plan-file` | Path to the plan diff output file (default `plan.txt`) |
| `plan-no-changes` | `"true"` if `ork plan` detected no changes — the deployed config is already up to date |
| `template-yaml-file` | Path to the YAML-rendered runtime Katalog |
| `template-json-file` | Path to the JSON-rendered runtime Katalog |
| `bundle-file` | Path to the generated `bundle.yaml` |
| `configmap-file` | Path to the generated `configmap.yaml` |
| `rbac-file` | Path to the generated `rbac.yaml` |
| `registry-file` | Path to the generated `zz_generated_runtime_registry.go` |
| `simulate-debug-file` | Path to the `--debug-ops` trace file (set when `simulate-debug: true`) |
| `pattern-path` | Local path where the pulled pattern was extracted |

---

## Examples

### Standard CI — validate, simulate, e2e

The CI pyramid: each layer is cheaper than the next. Simulate catches logic errors without a cluster.

```yaml
- uses: orkspace/orkestra-action@v1
with:
validate: "true"
simulate: "true" # reads simulate.yaml → fails on assertion errors
e2e: "true" # reads e2e.yaml → full cluster test
```

### Simulate with explicit katalog and CR

Use when you want to run simulate directly against a katalog without a `simulate.yaml` file.

```yaml
- uses: orkspace/orkestra-action@v1
with:
simulate-katalog: ./katalog.yaml
simulate-cr: ./cr.yaml
simulate-cycles: "5"
```

### Discovery mode — simulate and e2e across all examples

```yaml
- uses: orkspace/orkestra-action@v1
with:
simulate-depth: full
simulate-skip: "vendor,testdata"
e2e-depth: full
e2e-skip: "vendor,testdata"
e2e-wait: "5s"
```

### Matrix across multiple operators

```yaml
strategy:
matrix:
example:
- examples/beginner/01-hello-website
- examples/beginner/02-with-service
- examples/advanced/09-hooks

steps:
- uses: actions/checkout@v4
- uses: orkspace/orkestra-action@v1
with:
working-directory: ${{ matrix.example }}
validate: "true"
simulate: "true"
e2e: "true"
```

### Generate and upload a deployment bundle

```yaml
- name: Generate bundle
uses: orkspace/orkestra-action@v1
id: bundle
with:
generate-bundle: ./katalog.yaml

- name: Upload
uses: actions/upload-artifact@v4
with:
name: bundle
path: ${{ steps.bundle.outputs.bundle-file }}
```

### Typed operator — generate registry, build image, deploy, then e2e

```yaml
- uses: orkspace/orkestra-action@v1
with:
validate: "true"
simulate: "true"
generate-registry: "."

- run: CGO_ENABLED=0 go build -tags runtime -o ./bin/operator ./cmd/operator

- uses: docker/build-push-action@v5
with:
context: .
push: true
tags: ghcr.io/myorg/my-operator:${{ github.sha }}

- run: |
helm upgrade --install orkestra orkestra/orkestra \
--set runtime.image.repository=ghcr.io/myorg/my-operator \
--set runtime.image.tag=${{ github.sha }} \
--namespace orkestra-system --create-namespace --wait

- uses: orkspace/orkestra-action@v1
with:
e2e: "true"
e2e-cluster: kind-ork-e2e
```

See [`examples/typed-operator.yml`](examples/typed-operator.yml) for the full workflow.

### Plan diff commented on PR

Add `comment-on-pr: "true"` to post the plan diff as a PR comment. The job needs `pull-requests: write`.

```yaml
jobs:
plan:
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write
steps:
- uses: actions/checkout@v4
- uses: orkspace/orkestra-action@v0.1.0
with:
plan: katalog.yaml
plan-bundle: bundle.yaml
comment-on-pr: "true"
```

The comment shows the full `ork plan` diff. If there are no changes, it posts a clean "no changes" message instead. Output is truncated at 60,000 characters to stay within GitHub's comment limit.

**Cross-job pattern** — when you need the plan job to have minimal permissions and the comment job to have `pull-requests: write` separately:

```yaml
jobs:
plan:
runs-on: ubuntu-latest
permissions:
contents: read
outputs:
plan-no-changes: ${{ steps.ork.outputs.plan-no-changes }}
steps:
- uses: actions/checkout@v4
- name: Run ork plan
id: ork
uses: orkspace/orkestra-action@v0.1.0
with:
plan: katalog.yaml
plan-bundle: bundle.yaml
- uses: actions/upload-artifact@v4
if: steps.ork.outputs.plan-no-changes != 'true'
with:
name: ork-plan-${{ github.run_id }}
path: ${{ steps.ork.outputs.plan-file }}
retention-days: 3

comment:
needs: plan
runs-on: ubuntu-latest
permissions:
pull-requests: write
steps:
- uses: orkspace/orkestra-action/comment-plan-on-pr@v0.1.0
with:
plan-artifact: ork-plan-${{ github.run_id }}
no-changes: ${{ needs.plan.outputs.plan-no-changes }}
plan-status: ${{ needs.plan.result }}
github-token: ${{ secrets.GITHUB_TOKEN }}
```

See [`examples/plan-pr.yml`](examples/plan-pr.yml) for both patterns side by side.

### Publish a pattern on tag push

```yaml
- uses: orkspace/orkestra-action@v1
with:
validate: "true"
simulate: "true"
registry-push: "my-operator:${{ github.ref_name }} ."
registry-url: "ghcr.io/${{ github.repository_owner }}/patterns"
registry-username: ${{ github.actor }}
registry-password: ${{ secrets.GITHUB_TOKEN }}
```

---

## License

[Apache 2.0](./LICENSE)