StarSling
Getting Started

Quickstart

Migrate to StarSling Runners in under 5 minutes

View Markdown

2,000 free minutes for your first month — no credit card required.

Step 1: Install the StarSling GitHub App

Install the StarSling GitHub App in your organization:

Grant access to the org repositories where you want to use StarSling Runners.

StarSling Runners are not available for personal repositories, only GitHub organizations. If you install the GitHub App in a personal repo, StarSling Runners will not pick up the jobs. Learn why →

Step 2: Update Your Workflow(s)

Option A: Use an AI Prompt

Paste this prompt into any AI coding agent (Claude Code, Cursor, Codex, etc.):

AI prompt
# Migrate GitHub Actions to StarSling Runners

Migrate the user's workflows from GitHub-hosted runners to StarSling Runners.

**Prerequisites:** `gh` CLI authenticated, [StarSling GitHub App](https://github.com/apps/starslingdev) installed on the repo's org.

## Configuration

**Target:** `starsling-ubuntu-24.04` | **Branch:** `migrate-starsling-ubuntu-2404`

**Source runners to replace:** `ubuntu-latest`, `ubuntu-24.04`

Replace all UPPERCASE placeholders (`OWNER`, `REPO`, `BRANCH_NAME`, `HEAD_OID`, `BASE64_CONTENT`, `FILE_NAME`, `N`, `DEFAULT_BRANCH`) with actual values from previous steps.

## Procedure

### Step 1: Confirm GitHub App Installation

Ask the user: "Have you installed the [StarSling GitHub App](https://github.com/apps/starslingdev) on your org? It's required for runners to pick up jobs after merge. If not, please install it first and let me know when you're ready."

**Do not run any commands or proceed to Step 2 until the user explicitly confirms the app is installed.**

### Step 2: Verify CLI Auth

Verify `gh auth status` succeeds. If not, direct the user to install from https://cli.github.com/ and run `gh auth login`.

### Step 3: Get Repository

Ask the user for the repository (`owner/repo`). Then run `gh api repos/OWNER/REPO --jq '.owner.type'`. If the result is `User` (not `Organization`), stop and explain: "StarSling Runners only work with GitHub organization repositories. You can create a free organization at https://github.com/account/organizations/new."

### Step 4: Discover Workflows

Fetch all workflow files in one API call:

```bash
cat <<'QUERY' | gh api graphql --input -
{
  "query": "query($owner: String!, $repo: String!) { repository(owner: $owner, name: $repo) { id nameWithOwner defaultBranchRef { name target { oid } } object(expression: \"HEAD:.github/workflows\") { ... on Tree { entries { name object { ... on Blob { text } } } } } } }",
  "variables": { "owner": "OWNER", "repo": "REPO" }
}
QUERY
```

Note: `HEAD` in the GraphQL expression is a Git ref, not a placeholder — do not replace it.

If the response is truncated or errors due to size, fall back to the REST API: fetch the default branch and HEAD SHA via `gh api repos/OWNER/REPO --jq '.default_branch'` and `gh api repos/OWNER/REPO/git/ref/heads/DEFAULT_BRANCH --jq '.object.sha'`, then fetch workflow file names via `gh api repos/OWNER/REPO/contents/.github/workflows` and each file individually via `gh api repos/OWNER/REPO/contents/.github/workflows/FILE_NAME`. The response `content` field is base64-encoded — decode it before scanning for `runs-on:` values.

Save `defaultBranchRef.name` (or REST default branch), `.target.oid` / HEAD SHA, and workflow `entries[]`. Scan each `.yml`/`.yaml` file for:
- direct `runs-on:` string values matching supported runners, and
- matrix-driven patterns (e.g., `runs-on: ${{ matrix.os }}`) where the matrix values include supported runner labels.

Show the user a summary including:
- Workflows that will be migrated and which runners are being replaced
- Any Ubuntu runners NOT in the supported list (e.g., `ubuntu-22.04`, `ubuntu-20.04`, larger runners like `ubuntu-latest-16-cores`) listed as "Not migrated — unsupported runner label"

If no direct or matrix-backed supported runners match, stop.

### Step 5: Preview Changes

**Never create a PR without the user confirming changes first.**

Show what will change per workflow:
- Replace supported runners in `runs-on:` string values with `starsling-ubuntu-24.04` (preserve quotes/comments)
- Replace matching `runner:`/`os:` values in `matrix.include` sections
- Skip commented lines

**Complex `runs-on` patterns:**
- **Array syntax** (e.g., `runs-on: [self-hosted, linux, ubuntu-latest]`): Only replace the matching label within the array; do not collapse to a single string
- **Group/labels syntax** (e.g., `runs-on: { group: ..., labels: [...] }`): Skip and flag for manual review
- **Expressions** (`${{ matrix.os }}`, ternary/conditional): If `runs-on` uses `${{ matrix.os }}` and the matrix values are hardcoded runner labels, replace the labels in the matrix definition and flag the workflow for manual verification. If the matrix values come from other expressions, skip entirely and flag for manual review

**YAML fidelity:** Change ONLY the `runs-on` and matrix values. Preserve the original file exactly: same indentation, key ordering, comments, blank lines, and trailing newline. The PR diff should show only the runner label changes.

### Step 6: Create PR

**Branch:** Before creating, check for existing branches: `gh api repos/OWNER/REPO/git/matching-refs/heads/migrate-starsling-ubuntu-2404 --jq '.[].ref'`. If any exist, find the highest numeric suffix and increment by 1 (if none have a suffix, use `-2`). Then create: `gh api repos/OWNER/REPO/git/refs -f ref=refs/heads/BRANCH_NAME -f sha=HEAD_OID`.

**Atomic commit** — all files in one commit, contents base64-encoded:

```bash
cat <<'MUTATION' | gh api graphql --input -
{
  "query": "mutation($input: CreateCommitOnBranchInput!) { createCommitOnBranch(input: $input) { commit { oid url } } }",
  "variables": {
    "input": {
      "branch": {
        "repositoryNameWithOwner": "OWNER/REPO",
        "branchName": "BRANCH_NAME"
      },
      "message": {
        "headline": "Migrate N CI workflows to StarSling Runners",
        "body": "Replaced runners per file:\n- file1.yml: ubuntu-latest → starsling-ubuntu-24.04\n- file2.yml: ubuntu-24.04 → starsling-ubuntu-24.04"
      },
      "expectedHeadOid": "HEAD_OID",
      "fileChanges": {
        "additions": [
          { "path": ".github/workflows/FILE_NAME", "contents": "BASE64_CONTENT" }
        ]
      }
    }
  }
}
MUTATION
```

Verify the response contains a valid `commit.oid`. If the mutation returned an `expectedHeadOid` mismatch, re-fetch the HEAD SHA (Step 4) and retry the commit once. For any other errors, report and stop — do not create a PR against a failed commit.

**Commit message:** The headline should read `Migrate N CI workflows to StarSling Runners` where N is the count of modified workflow files (`.yml` + `.yaml`). List each file and the runner label(s) replaced in the body, as shown in the example above.

**PR** via `gh pr create --repo OWNER/REPO --head BRANCH_NAME --base DEFAULT_BRANCH --title "Migrate N CI workflows to StarSling Runners" --body "..."` with this body structure:

```
## Summary
Migrates CI workflows from GitHub-hosted runners to [StarSling Runners](https://docs.starsling.dev) for faster builds and AI-powered optimizations.

## Changes
- `file1.yml`: `ubuntu-latest` → `starsling-ubuntu-24.04`
- `file2.yml`: `ubuntu-24.04` → `starsling-ubuntu-24.04`

## Not Migrated
- `file3.yml`: Uses `${{ matrix.os }}` — requires manual review
(or "All workflows migrated successfully.")

## After Merging
Workflows will automatically run on StarSling Runners. Ensure the [StarSling GitHub App](https://github.com/apps/starslingdev) is installed with access to this repo.
```

### Step 7: Monitor (Optional)

Ask the user if they'd like help monitoring after merge. If yes, explain they can return after merging and you'll check with:

```bash
gh run list --repo OWNER/REPO --branch DEFAULT_BRANCH --limit 5 --json status,conclusion,name,createdAt
```

Look for runs created after the merge. If any show `queued` for more than 2 minutes, suggest checking the GitHub App installation and repo access at https://github.com/apps/starslingdev.

## Error Handling

| Error | Solution |
|-------|----------|
| `gh` not found or not logged in | Install from https://cli.github.com/, run `gh auth login` |
| 403 / insufficient permissions | User needs write access to the repository — check collaborator status or org role |
| App not installed | Install from https://github.com/apps/starslingdev |
| Personal repo (owner type `User`) | StarSling requires an org repo — create one at https://github.com/account/organizations/new |
| Repository not found | Check repo name and permissions |
| No workflows found | Ensure `.github/workflows/` exists |
| Runner not available after merge | Verify app has repo access at https://github.com/apps/starslingdev |
| Rate limit exceeded | Wait a few minutes and retry |
| 422 on branch creation | Branch exists — append a number suffix |
| `expectedHeadOid` mismatch | Re-fetch HEAD SHA and retry the commit |
| `${{ matrix.os }}` / complex `runs-on` | Require manual review — determined at runtime |
| GraphQL response truncated | Fall back to REST API for individual file fetches |

Option B: Manual Update

Change your runs-on label from GitHub-hosted to StarSling:

starsling-ubuntu-24.04

Before

.github/workflows/ci.yml
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      # ... your build steps

After

.github/workflows/ci.yml
jobs:
  build:
    runs-on: starsling-ubuntu-24.04
    steps:
      - uses: actions/checkout@v4
      # ... your build steps

That's it. Push your changes and watch your builds fly.

Label Mapping

Use starsling-ubuntu-24.04 (4 vCPU / 16 GB) to replace these GitHub-hosted runner labels:

GitHub-hosted LabelStarSling Label
ubuntu-lateststarsling-ubuntu-24.04
ubuntu-24.04starsling-ubuntu-24.04

StarSling also offers additional runner sizes (2, 8, 16, 32, and 64 vCPU). See Linux Runners for the full label reference.

What's Next?

On this page