Skip to content

Testing recipe

Run real SMS tests in GitHub Actions

Run the same acceptance test against staging on a trusted main-branch push or a manual dispatch. GitHub Actions supplies the selected-number API key; the SDK waits inside the test; the job reports whether the application accepted the received code.

Configure a dedicated staging environment

Create a GitHub environment named sms-staging. Store PHONEKIT_API_KEY as an environment secret, and create environment variables TEST_PHONE_NUMBER and TEST_BASE_URL. Explicitly select the test number when issuing the Phonekit key. Add environment approval rules if your team uses them for staging credentials.

The target application must already be deployed and have the expected test account ready. If a deployment job is part of this workflow, make the test depend on that job and use its completed deployment URL.

Add the workflow

Place this file at .github/workflows/sms-acceptance.yml in the test project's repository. It uses your committed npm lockfile and the Playwright test. Use the equivalent lockfile command for a project managed with pnpm or another package manager.

.github/workflows/sms-acceptance.ymlYAML
name: Real SMS acceptance
 
on:
  workflow_dispatch:
  push:
    branches: [main]
 
permissions:
  contents: read
 
# All workflows using this number must use the same group.
concurrency:
  group: phonekit-staging-number-1
  cancel-in-progress: false
 
jobs:
  sms:
    runs-on: ubuntu-latest
    timeout-minutes: 10
    environment: sms-staging
    steps:
      - uses: actions/checkout@v6
      - uses: actions/setup-node@v6
        with:
          node-version: 24
          cache: npm
      - run: npm ci
      - run: npx playwright install --with-deps chromium
      - name: Verify staging sign-in
        run: npx playwright test tests/phone-verification.spec.ts --workers=1
        env:
          PHONEKIT_API_KEY: ${{ secrets.PHONEKIT_API_KEY }}
          TEST_PHONE_NUMBER: ${{ vars.TEST_PHONE_NUMBER }}
          TEST_BASE_URL: ${{ vars.TEST_BASE_URL }}

Prepare dependencies before the first run

Install the Phonekit SDK and Playwright in the project, commit the lockfile, and commit the browser test and configuration. npm ci must be able to resolve every dependency from a clean checkout. Before registry publication, install the public content-addressed candidate linked in the SDK guide. Its HTTPS URL and integrity are recorded in your lockfile, so a clean runner can install it without access to Phonekit’s private repository.

Use trace: "off", screenshot: "off", and video: "off" for this acceptance test unless you have a reviewed capture/redaction policy. Avoid uploading unrestricted verification screenshots with the ordinary browser report.

Serialize the resource you actually share

The fixed concurrency group serializes runs in this repository that use phonekit-staging-number-1. Use the same group in every workflow sharing that number. GitHub concurrency is not a queue guaranteeing every pending run will execute; it keeps at most one running and one pending run for the group. Use distinct numbers or a separate scheduler if each run must be processed.

See GitHub’s concurrency semantics.

For a parallel suite, allocate a number per worker or workflow and give each allocation its own group. One worker inside a job does not prevent a second job from using the same number.

Choose the trusted pull-request path

This workflow runs main-branch code and manual runs. Run fast fictional-code/UI tests on every pull request, then run real-delivery acceptance against a trusted deployment. GitHub generally withholds Actions secrets from fork pull requests. Avoid switching to pull_request_target to run untrusted checked-out code with the SMS key. See GitHub's secret availability guidance.

Make failures actionable

SymptomCheck
Required environment variable missingEnvironment name, secret/variable spelling, and permitted event
SDK reports unauthorized or unavailable numberRevocation and selected-number scope
Form send failsStaging deployment and sender's response
No fresh SMS before the deadlineNumber allocation, sender delivery and cooldown
Code received but account assertion failsSender validity and application's verification/session flow

Scroll horizontally to see all columns.

Use stage names, statuses and timings in diagnostics. Keep the API key and received SMS content inside the runner. The workflow foundation follows Playwright's GitHub Actions guidance; the staging resource and secret policy are specific to this Phonekit workflow.

Common questions

Do I run phonekit login in GitHub Actions?

No. The SDK takes the selected-number key from the job environment. Interactive browser approval belongs to local CLI setup, not an unattended acceptance job.

Why only main-branch pushes and manual dispatches?

Those events provide a straightforward trusted starting point for a secret-bearing test. Your team can add acceptance to its trusted deployment process. Fork pull requests should keep using tests that do not need the Phonekit key.

Will cancel-in-progress: false run every push?

No. It prevents canceling the running job, but GitHub may replace an already pending run in the same concurrency group. Allocate separate resources or use a queue if every acceptance run must execute.

Can two repositories share this concurrency group?

GitHub Actions concurrency is repository-scoped. A group with the same name in another repository will not coordinate access to the number. Assign a distinct number to each repository or use a shared external resource scheduler.

Why avoid an automatic resend loop when a test times out?

A new send may collide with a delayed first message and can hit the sender’s request limits. Diagnose the send/receipt/verification stage, then start a new explicit attempt with its own cursor and permitted resend timing.