# GitHub Action

> A workflow step that builds a brief from your diff on your runner and posts the pitch as a check.

There is no Raylight GitHub App. The Action is a normal workflow step: it runs on your runner, reads the checkout, builds a brief, and makes the same `POST /v1/productions` call you would make by hand to start a production. Raylight never gets a token for your repository and never calls GitHub.

## Setup

1. Create an API key with the `productions` scope (Raylight API, Keys) and add it to the repository as the `RAYLIGHT_API_KEY` secret.
2. Add a workflow. Check out with `fetch-depth: 0` so the Action can diff against the previous release, or from where a pull request branched off its base. With a shallow checkout it fetches the history it needs itself.
3. Pick how to greenlight: the production's page in the app, the Pitch ready email, or a webhook relay. They all answer the same production.

.github/workflows/launch-video.yml:

```yaml
name: Launch video

on:
  release:
    types: [published]

jobs:
  video:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      checks: write
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - uses: raylight-labs/video-action@v1
        with:
          api-key: ${{ secrets.RAYLIGHT_API_KEY }}
          intent: "Announce ${{ github.event.release.name }} to existing customers"
          template: launch
          duration-seconds: 15
          aspect: "16:9"
          greenlight-mode: manual
          code-globs: "src/**/*.tsx"
          wait-for-pitch: true
          post-check: true
```

## Inputs

| Input | Meaning | Default |
| --- | --- | --- |
| `api-key` | The `rl_live_` key. Pass it from a secret. | required |
| `intent` | The one sentence. Fill in the release or PR title with workflow expressions. | required |
| `context` | Longer context: release notes, the PR body, linked issues. | the PR body, the release notes, or on a push the head commit's message |
| `template` | `changelog`, `launch`, `feature`, `digest` or `custom`. | `changelog` |
| `duration-seconds` | Length of the video, 5 to 15. | 10 |
| `aspect` | `16:9`, `9:16`, `1:1` and the rest of the aspect list. | `16:9` |
| `greenlight-mode` | `manual` waits for someone to greenlight the pitch; `auto` greenlights a video verdict and charges immediately. | `manual` |
| `base-ref`, `head-ref` | The two ends of the diff. | the PR base, the previous release tag or the push's before sha; `GITHUB_SHA` |
| `code-globs` | Newline separated globs of files that may be sent as UI source. Nothing outside them leaves the runner. | UI source, style and script files outside `node_modules` and build output |
| `max-files` | Most changed files to send, up to 40. | 40 |
| `media` | Newline separated `url::name` lines for hosted images or videos. | none |
| `wait-for-pitch` | Hold the step (up to 10 minutes) until the pitch is ready and write it to the step summary. | `true` |
| `post-check` | Add a neutral check run named Raylight Video to the commit with the pitch, using the workflow's own token. | `true` |
| `api-url` | API origin. | `https://api.raylight.app` |
| `github-token` | Used on the runner for the check run and the previous release lookup. Never sent to Raylight. | `github.token` |

With `post-check` the reviewer sees the pitch in GitHub: the check shows the shots and the price and links to the production's page in Raylight, where anyone on the workspace can greenlight it, send comments or decline. Login-free [greenlight links](https://www.raylight.app/docs/greenlight-links.md) go out in the Pitch ready email and on webhooks. They are not part of the API response the Action reads, so they never appear in the check. The check only needs `checks: write` on the job's permissions; the token stays on the runner.

## Outputs

| Output | Value |
| --- | --- |
| `production-id` | The production's id. Always set. |
| `production-url` | The production's page in Raylight. Always set. |
| `stage` | The stage value when the step finished. `pitch_ready` (Pitch ready) is the usual answer with `greenlight-mode: manual`. |
| `pitch-markdown` | The pitch as markdown, when it was ready within the wait. |
| `share-url` | The share link, when `greenlight-mode: auto` and the video wrapped within the wait. Otherwise empty; the link arrives by webhook and email. |

## What leaves the runner

Only the brief:

- `brief.intent` from the `intent` input.
- `brief.context`: the `context` input, or else the PR body, the release notes, or on a push the head commit's message, cut to 60,000 characters.
- `brief.media`: the `media` URLs, if any.
- `brief.code`: for each changed file matching `code-globs`, its path, contents at the head commit, change status, line counts, diff hunks (capped at 20,000 characters), a digest and a score, all computed on the runner. Files that usually hold secrets (`.env` files, keys, `.npmrc`, cloud credentials), symlinks and submodules are never sent, and anything shaped like a key or token is masked in what is.
- `brief.format` from `template`, `duration-seconds` and `aspect`.
- `origin`: provider `github`, the repository and release tag or PR number as the label, the HTML URL, the head commit, and the actor's login.
- `externalId`: the repository plus the event and the release tag or PR number. Before reading the diff, the Action looks that id up (`GET /v1/productions?externalId=...`, which sends nothing else); a re-run, a reopened pull request or a second label finds the first run's production and sends nothing. A pull request gets one production: runs for new pushes to it are skipped before anything is sent.
- `greenlightMode` from `greenlight-mode`.

No repository token, no environment, no files outside the globs, no history beyond the diff. The Action is open source at `github.com/raylight-labs/video-action`, and the request body is built in one place you can read.

## On a labelled pull request

Add a `video` label to a pull request to get a feature video for it. The production's origin points at the PR, and the check lands on its head commit.

.github/workflows/feature-video.yml:

```yaml
name: Feature video

on:
  pull_request:
    types: [labeled]

jobs:
  video:
    if: github.event.label.name == 'video'
    runs-on: ubuntu-latest
    permissions:
      contents: read
      checks: write
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - uses: raylight-labs/video-action@v1
        with:
          api-key: ${{ secrets.RAYLIGHT_API_KEY }}
          intent: "${{ github.event.pull_request.title }}"
          template: feature
          code-globs: "src/**/*.tsx"
          wait-for-pitch: true
          post-check: true
```

## After the step

The workflow ends once the pitch exists; Raylight makes the video after someone greenlights it. The finished video arrives by email, on any [webhook](https://www.raylight.app/docs/webhooks.md) you registered, and on the Productions page in the app. To post the share link back to the PR, point a webhook at a small relay; the [recipes](https://www.raylight.app/docs/recipes.md) include one.

## More

- Previous: [Greenlight links](https://www.raylight.app/docs/greenlight-links.md)
- Next: [CLI](https://www.raylight.app/docs/cli.md)
- All docs: https://www.raylight.app/llms.txt
- Everything in one file: https://www.raylight.app/llms-full.txt
- OpenAPI: https://api.raylight.app/v1/openapi.json
