A GitHub action to setup the Runway CLI! Questions, issues? Please use discussions or the issue tracker on the repository. If you like what you see here, we appreciate a ⭐ and if you'd subscribe to (our monthly) mailing list and check out the website to stay in the loop!
This action supports amd64 and arm64 Linux runners.
Tip
API keys are new in Runway CLI v1.45.0 (July, 2026).
permissions:
contents: read
jobs:
runway:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7.0.1
with:
persist-credentials: false
fetch-depth: 0
- uses: hostwithquantum/setup-runway@v0.6.0
with:
api-key: ${{ secrets.RUNWAY_API_KEY }}
- run: runway whoamiAlternatively, log in with username/password:
- uses: hostwithquantum/setup-runway@v0.6.0
with:
username: ${{ secrets.RUNWAY_USERNAME }}
password: ${{ secrets.RUNWAY_PASSWORD }}
- run: runway whoamiThe currently supported inputs:
| option | default value | description |
|---|---|---|
| username | empty | username/email for Runway |
| password | empty | password for Runway |
| api-key | empty | Runway API key, takes precedence over username/password |
| application | empty | Runway application (will be created or added) |
| add-key | false |
if set to true, add the ssh key to Runway |
| setup-ssh | false |
if set to true, setup ssh for runway app deploy |
| log-level | error |
debug, info, warn, error |
| public-key | empty | a public ssh key (from a secret) |
| private-key | empty | a public ssh key (from a secret) |
| public-key-location | ~/.ssh/id_rsa.pub |
ssh public key location |
| public-key-location | ~/.ssh/id_rsa |
ssh private key location |
| version | latest |
runway cli version |
| controller | empty | controller URL for Enterprise installations |
Tip
For the Runway CLI version, latest is fine. We strive to never break your workflows. But sometimes BC breaks are necessary. Because they usually involve our client and APIs, using latest helps to keep all interruptions to a minimum.
Important
There's a BC break in this action in v0.5.0, previously the public-key and private-key inputs contained paths. They have been renamed to public-key-location and private-key-location to make their purpose more clear. The new public-key and private-key inputs are optional and contain your (SSH) public and private key if used.
The following examples show how this action and the Runway CLI can be used in workflows.
This is an example workflow which shows Runway CLI setup and then how to use the CLI to deploy your application cool-app.
Once the CLI is setup, you can run all commands and play around with output and so on. To keep it simple, we're only deploying the code. :) Since the application exists already on Runway we use the runway gitremote command to initialize the setup.
# .github/workflows/release.yml
name: release
on:
push:
tags: ['v*']
permissions:
contents: read
jobs:
deploy:
runs-on: ubuntu-latest
env:
APP_NAME: cool-app
steps:
- uses: actions/checkout@v7.0.1
with:
persist-credentials: false
fetch-depth: 0 # this is important
- uses: hostwithquantum/setup-runway@v0.6.0
with:
api-key: ${{ secrets.RUNWAY_API_KEY }}
application: ${{ env.APP_NAME }}
private-key: ${{ secrets.PRIVATE_KEY }}
public-key: ${{ secrets.PUBLIC_KEY }}
- run: runway app deploy
- run: runway logoutWhen you invoke this action with an application input, we'll either create or attach an existing application with that name. By default we create an application on the free tier, but if you need to customize the runway app create, then skip the application input and do this instead in a regular run step.
This examples creates an application on the Pro Plan with persistence enabled:
# .github/workflows/ci.yml
on: pull_request
permissions:
contents: read
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: hostwithquantum/setup-runway@v0.6.0
with:
api-key: ${{ secrets.RUNWAY_API_KEY }}
public-key: ${{ secrets.DEPLOY_PUBLIC_KEY }}
private-key: ${{ secrets.DEPLOY_PRIVATE_KEY }}
- run: |
runway app create \
-a my-fancy-name \
-p pro-m-launch \
--persistence
- if: always()
run: runway logoutGitHub Actions provides a robust and comprehensive environment to run e2e tests and here's how Runway can help:
The following workflow leverages some of the context in form of the pull-request's number: ${{ github.event.number }}. We'll use this identifier to deploy an application with a unique name.
Once deployed, you can run end-to-end tests against it and in the end, shut it down by deleting the application (and key). :) If you decide to keep the application to have a preview available, you may also do that.
Tip
If you plan to use this feature with e.g. dependabot, then ensure to add the appropriate secrets for dependabot on your repository settings.
# .github/workflows/e2e.yml
name: e2e
on: pull_request
permissions:
contents: read
jobs:
deploy_app:
runs-on: ubuntu-latest
timeout-minutes: 15
env:
APP_NAME: my-app-${{ github.event.number }}
KEY_NAME: test-key-${{ github.event.number }}
steps:
- uses: actions/checkout@v7.0.1
with:
persist-credentials: false
fetch-depth: 0 # this is important!
- name: create an ssh key just for this run
run: |
mkdir -p ~/.ssh/
ssh-keygen -b 2048 -t rsa -f ~/.ssh/test-runner -c "${KEY_NAME}" -q -N ""
- name: install Runway CLI, login and add ssh key
uses: hostwithquantum/setup-runway@v0.6.0
with:
api-key: ${{ secrets.RUNWAY_API_KEY }}
application: ${{ env.APP_NAME }}
public-key-location: ~/.ssh/test-runner.pub
private-key-location: ~/.ssh/test-runner
add-key: true
setup-ssh: true
- name: deploy your application to Runway
run: runway app deploy
# this is where your tests run!
- name: run your e2e tests here
run: curl https://${APP_NAME}.pqapp.dev/
# then hopefully you are done :)
- name: cleanup application
if: always()
run : runway app rm -a ${APP_NAME} || true
- name: cleanup key - this is brute force
if: always()
run: runway key rm "${KEY_NAME}" || true
- name: logout
if: always()
run: runway logoutIn the previous example, we created an application to run our tests. But another great use-case are preview-apps — they allow you to create a demo of your changes. The following workflow shows how to deletes an application from Runway when a pull-request is closed (merged or closed without merge).
Important
This example assumes that you constructed the application with a stable identifier, e.g. my-app-${{ github.event.number }}. In a pull-request context, the ${{ github.event.number }} is the ID/number of the pull-request.
# .github/workflows/delete-preview.yml
name: delete app
on:
pull_request:
types: [closed]
jobs:
delete:
runs-on: ubuntu-latest
env:
APP_NAME: my-app-${{ github.event.number }}
steps:
- uses: hostwithquantum/setup-runway@v0.6.0
with:
api-key: ${{ secrets.RUNWAY_API_KEY }}
- run: runway app rm ${APP_NAME}
- if: always()
run: runway logout