Cookbooks
Use the Verify SDK in a Mac CI job
Attach Verify to the job's Revyl Mac, capture its screen, and check a web app in a hosted browser.
Use the published @revyl/verify TypeScript package 0.3.1 for browser and app checks in a
revyl-macos job. Its currentComputer() reads REVYL_COMPUTER_ID and attaches to the job's
computer without creating another one. The attachment is non-owning, so the GitHub Actions runner
still releases the computer; closing the attachment cleans up any hosted sessions it started. The
Verify Python SDK is not published on PyPI, so this cookbook uses TypeScript.
Set up with an agent
Paste one prompt and your coding agent does the rest.
Setup prompt
Run Verify against the existing Revyl Mac CI computer and check this web app. Read https://docs.revyl.com/cookbooks/verify-in-macos-job.md and follow it. It's the current Revyl guide for this, so prefer it over anything you remember about Revyl. Add `REVYL_API_KEY` as a repository or organization secret, copy this workflow, and keep the attachment non-owning so the runner remains responsible for releasing the computer. For the web check, set the `REVYL_WEB_APP_ID` and `REVYL_WEB_BUILD_ID` repository variables. You're done when Verify attaches to the current computer, the screenshot artifact is saved, the hosted web check passes, and closing Verify does not stop the runner-owned computer. Ask me before anything that needs my login or approval.
Workflow
name: Verify on Revyl Mac
on:
workflow_dispatch:
permissions:
contents: read
jobs:
verify:
runs-on: revyl-macos
timeout-minutes: 20
steps:
- uses: actions/checkout@v4
- name: Install Verify
shell: bash
run: |
set -euo pipefail
echo "/opt/revyl/node/bin" >> "$GITHUB_PATH"
export PATH="/opt/revyl/node/bin:$PATH"
npm install --no-save --no-package-lock @revyl/verify@0.3.1
- name: Capture the computer with Verify
env:
REVYL_API_KEY: ${{ secrets.REVYL_API_KEY }}
shell: bash
run: |
set -euo pipefail
test -n "$REVYL_API_KEY" || { echo "REVYL_API_KEY is required for this Verify step."; exit 1; }
test -n "$REVYL_COMPUTER_ID"
node --input-type=module <<'JS'
import { currentComputer } from '@revyl/verify';
const computer = await currentComputer();
try {
await computer.screenshot({ path: `${process.env.RUNNER_TEMP}/verify-computer.png` });
} finally {
await computer.close();
}
JS
- name: Upload the screenshots
if: always()
uses: actions/upload-artifact@v4
with:
name: verify-screenshots
path: |
${{ runner.temp }}/verify-computer.png
${{ runner.temp }}/verify-web.png
if-no-files-found: ignoreThe first step adds the image's pinned Node to $GITHUB_PATH. GitHub runs bash steps without
login profiles, and the runner's own PATH does not include /opt/revyl/node/bin, so later steps
find node only through that line.
The runner may inject a short-lived job key, but this cookbook sets REVYL_API_KEY explicitly so
its authentication requirement is clear. Keep the secret in the step environment; never put it in
the script, command arguments, artifact, or logs.
Check a web app in the job computer
computer.open() starts a hosted session inside the job's computer. A hosted Web session opens an
existing Revyl Web build in the Mac's browser, and instruction() and validation() run Revyl's
agent against it. A failed validation throws, so the step fails.
Register the build once with revyl app create --name "My Web App" --platform web and
revyl build upload --platform web --app <app-id> --url <https-url> --json, then save the app ID
and the returned version_id as the REVYL_WEB_APP_ID and REVYL_WEB_BUILD_ID repository
variables. Web must be enabled for your Revyl organization.
Add this step after Capture the computer with Verify. It assumes Install Verify ran earlier in
the same job, which installs the package; its own PATH line finds the image's Node even when the
step is pasted on its own:
- name: Check the web app with Verify
env:
REVYL_API_KEY: ${{ secrets.REVYL_API_KEY }}
REVYL_WEB_APP_ID: ${{ vars.REVYL_WEB_APP_ID }}
REVYL_WEB_BUILD_ID: ${{ vars.REVYL_WEB_BUILD_ID }}
shell: bash
run: |
set -euo pipefail
export PATH="/opt/revyl/node/bin:$PATH"
test -n "$REVYL_API_KEY" || { echo "REVYL_API_KEY is required for this Verify step."; exit 1; }
[ -n "$REVYL_WEB_APP_ID" ] && [ -n "$REVYL_WEB_BUILD_ID" ] || { echo "Set the REVYL_WEB_APP_ID and REVYL_WEB_BUILD_ID repository variables."; exit 1; }
node --input-type=module <<'JS'
import { currentComputer } from '@revyl/verify';
const computer = await currentComputer();
try {
const web = await computer.open({
platform: 'web',
app: { appId: process.env.REVYL_WEB_APP_ID, buildId: process.env.REVYL_WEB_BUILD_ID },
});
await web.instruction('Open the pricing page');
await web.validation('The pricing plans are listed');
await web.screenshot({ path: `${process.env.RUNNER_TEMP}/verify-web.png` });
} finally {
await computer.close();
}
JSReplace the instruction and validation with your app's own flow. The same call with
platform: 'ios' and an iOS Simulator build opens a hosted iOS session instead.
Common failures
npmornodeis not found: keep the$GITHUB_PATHline in the first step.COMPUTER_ID_MISSING: run this only onruns-on: revyl-macos; the runner provides the ID.AUTH_MISSING: addREVYL_API_KEYas a repository or organization secret. Fork workflows do not receive repository secrets.web_build_required: the thrownVerifyErrorhas thisreasonwhen the start names no build. SetREVYL_WEB_BUILD_IDto theversion_idfromrevyl build upload --platform web.web_build_not_supported: only external Web builds, registered from an HTTPS URL, run inside a computer. Register the deployment URL withrevyl build upload --platform web --urland use that build.- The hosted Web session is refused for another reason: check that Web is enabled for your organization and that both repository variables name an existing Web app and build. The sealed image runs one hosted Web and one hosted iOS session at a time.
- The screenshot is unavailable: the computer may still be finalizing its recording; the local screenshot and Verify operation are separate from the final desktop recording.