How to Configure Argos CI for GitLab CI Pipelines
Add Argos visual testing to GitLab CI: capture screenshots, upload them with a protected token, validate the pipeline, and troubleshoot common failures.
To configure Argos in a GitLab CI pipeline, run your screenshot-producing tests in a GitLab job and upload the resulting screenshots with an Argos project token. The Argos Node.js SDK reads ARGOS_TOKEN by default. Store that token as a protected CI variable and expose it only to the job that uploads screenshots.
The examples below use Playwright to write PNG files and the Argos core SDK to upload them. They are integration patterns based on the documented SDK and GitLab pipeline model; adapt the image, setup commands, stage names, and pipeline rules to your repository. Argos documents GitLab support and visual comparison in its CI integration guide; see the Argos Node.js SDK reference for current upload options.
1. Choose how your project will capture screenshots
Argos receives screenshots; your test framework or application must produce them. Choose a capture route that fits the project:
- Existing Playwright tests: have tests write screenshots into a directory, then upload that directory. This keeps capture and upload as separate steps and works with an existing test suite.
- Argos Playwright integration: use the Argos Playwright package when you want its framework-specific integration. Check its current setup instructions before adding a reporter or helper; the exact configuration depends on your Playwright version and test setup.
- Other frameworks: create PNG screenshots with your framework, then upload them with the Node.js SDK. The SDK accepts a root directory and file globs.
This guide uses directory upload so the GitLab job remains straightforward and the test framework can be changed independently.
2. Prepare the project and token
- Set up the Argos project and obtain its project token. Use Argos’s current account and project instructions; this guide does not assume a particular onboarding flow.
- In GitLab, add the token as a CI/CD variable named
ARGOS_TOKEN. Apply the project’s secret-variable practices, including masking and protection where appropriate. Limit availability to the upload job if your pipeline allows it. - Ensure the job can install dependencies and run the app or test environment needed for screenshot capture.
The SDK uses ARGOS_TOKEN by default, so the example uploader does not put the secret in source code or a command line. Avoid committing the token, printing it, or passing it as a literal in .gitlab-ci.yml.
3. Add screenshot capture and upload code
Install the SDK and Playwright in the project that owns the tests. Use your normal package manager and lockfile:
npm install --save-dev @argos-ci/core playwright
Here is a minimal Playwright script that opens a local application and writes a screenshot. Replace the URL with the URL reachable from the CI job and add the page setup and assertions your application needs.
// scripts/capture.mjs
import { chromium } from "playwright";
const browser = await chromium.launch({ headless: true });
try {
const page = await browser.newPage({ viewport: { width: 1280, height: 800 } });
await page.goto(process.env.APP_URL ?? "http://127.0.0.1:3000", {
waitUntil: "networkidle",
timeout: 30_000,
});
await page.screenshot({ path: "screenshots/home.png", fullPage: true });
} finally {
await browser.close();
}
Install the browser required by your project in the job image or setup step. For Playwright, use the installation command appropriate to the version pinned by your lockfile. A common Linux setup is npx playwright install --with-deps chromium; check the official Playwright CI documentation for supported container and dependency details.
Create a separate uploader. It exits with an error if the token is absent and uploads PNG files under screenshots/:
// scripts/upload-argos.mjs
import { upload } from "@argos-ci/core";
if (!process.env.ARGOS_TOKEN) {
throw new Error("ARGOS_TOKEN is required to upload screenshots");
}
const { build } = await upload({
root: "./screenshots",
files: ["**/*.png"],
});
console.log(`Argos build created: ${build.url}`);
The token is omitted from the options because the SDK defaults to ARGOS_TOKEN. The SDK reference also supports providing token: process.env.ARGOS_TOKEN explicitly, which can be useful when your code passes a token through a different variable.
4. Add the GitLab CI job
GitLab runs pipeline jobs defined in .gitlab-ci.yml. Stages run in order, and jobs in a stage can run in parallel when runners are available. A runner must be available to execute this job. GitLab’s documentation describes pipeline configuration in its CI/CD guide and lists the keywords in the YAML reference.
This example assumes the repository has a working npm ci, an npm run build script, and a npm run test:e2e script that leaves PNG screenshots in screenshots/. Adjust these assumptions to match your application. If the app needs to run locally during the test, start it in the test script or add a managed background service and readiness check.
stages:
- test
visual-regression:
stage: test
image: mcr.microsoft.com/playwright:v1.55.0-noble
variables:
APP_URL: "http://127.0.0.1:3000"
script:
- npm ci
- npm run build
- npm run test:e2e
- node scripts/upload-argos.mjs
rules:
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
- if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
Pin the Playwright container tag to match the Playwright version in your project rather than copying the sample tag blindly. If your existing pipeline already builds and tests the app, add the upload after those prerequisites or put it in a dedicated job that depends on their artifacts. Do not add another job that repeats expensive setup unless it is needed.
Dedicated job or existing test job?
| Pattern | Use it when | What to account for |
|---|---|---|
| Upload in the test job | The same job captures the screenshots and already has the app and browser ready. | Keep the token limited to that job where possible; an upload failure will fail the combined job. |
| Dedicated upload job | A prior job creates screenshots as artifacts, or you want upload setup isolated. | Download the screenshot artifact, declare job ordering with needs or stages, and ensure the token is available to this job. |
| Framework-specific Argos integration | You want Argos’s supported integration for your test framework. | Follow the current integration documentation for the exact reporter or helper settings and token behavior. |
For a separate uploader job, the capture job must publish the screenshot directory as a GitLab artifact, and the uploader must download it. A minimal structure looks like this; keep the build and test commands appropriate to your project:
stages:
- test
- visual-upload
capture-screenshots:
stage: test
image: mcr.microsoft.com/playwright:v1.55.0-noble
script:
- npm ci
- npm run build
- npm run test:e2e
artifacts:
paths:
- screenshots/
expire_in: 1 day
upload-argos:
stage: visual-upload
image: node:22
needs:
- job: capture-screenshots
artifacts: true
script:
- npm ci
- node scripts/upload-argos.mjs
rules:
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
- if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
This second example assumes the capture job can install and run the browser and that its artifact includes the expected PNG files. If the uploader runs npm ci, the SDK must be a project dependency and the lockfile must be available. You can instead publish a small artifact containing only the uploader and required runtime files, depending on your repository structure.
5. Validate and run the pipeline
- Check the complete merged pipeline configuration, including any
includefiles, variables, rules, and inherited defaults. - Validate
.gitlab-ci.ymlwith GitLab’s CI Lint. It can check syntax and simulate pipeline creation to catch some rule and dependency problems. - Confirm that the target branch and pipeline type satisfy the job’s
rules. A job configured only for merge request pipelines will not run for every push pipeline. - Run a pipeline where the job has access to the token. Verify that screenshot files exist before upload and that the job log does not reveal secrets.
- Open the resulting Argos build and review detected visual differences against its baseline. The precise review and GitLab status behavior can depend on your integration and current Argos configuration; use Argos’s current documentation for those details.
GitLab describes the configuration format this way: “Pipelines are configured in a .gitlab-ci.yml file by using YAML keywords.” See the GitLab YAML reference for the complete keyword behavior.
Configuration choices that affect the result
When the job runs
Use rules to choose whether visual captures run on merge requests, default-branch pushes, schedules, or selected paths. Keep rules consistent with where your baselines should be produced and what your team intends to review. Test rule changes with CI Lint’s pipeline simulation; a valid YAML file can still produce no job for a particular event.
How jobs are ordered
Use stages for a simple “build, then capture” sequence. Use needs when a job should depend on a specific earlier job and, where applicable, consume its artifacts. If the browser job starts before the app is ready, screenshots may capture an error page or incomplete UI.
How screenshots are selected
The SDK upload example sets root to the screenshot directory and files to a glob. Match the glob to the files your tests actually create. For example, **/*.png recursively includes PNGs; use a suitable pattern if you intentionally produce another supported image type. Avoid uploading unrelated generated images from a broad directory.
How the token is supplied
The SDK defaults to ARGOS_TOKEN. You can make the source explicit with token: process.env.ARGOS_TOKEN, but that does not replace configuring the CI variable. Protect the variable according to your branch and merge request policy: protected variables may not be exposed to pipelines on unprotected refs, depending on GitLab settings. If the job cannot see the secret, check variable scope and ref protection without printing the secret itself.
Parallel tests and shards
If a test suite is split across jobs, ensure each shard’s screenshots are associated with the intended visual build and that no job silently overwrites another shard’s files. Argos’s current CI documentation describes parallel and integration-specific behavior; follow it before introducing parallel upload configuration. The simple single-job examples here do not configure sharding.
Common errors and fixes
| Symptom | Likely cause | Fix |
|---|---|---|
| The job is stuck or never starts. | No matching runner is available, or runner tags and project settings prevent assignment. | Check runner availability, tags, and project access. GitLab requires an active runner to execute the job. |
| The pipeline is valid but the visual job is missing. | rules do not match the event, branch, or changed paths. |
Inspect the pipeline source and branch values; validate with CI Lint simulation. Adjust rules for the events you intend to cover. |
| Upload fails because the token is missing. | ARGOS_TOKEN is unset, scoped to another environment, or unavailable on the branch/ref. |
Check the CI variable name, scope, protected status, and job context. Do not echo the token to diagnose it. |
| Upload finds no screenshots. | The test did not write images, used another directory or extension, or the glob does not match. | List the expected directory in the job log, verify test output paths, and align root and files with those paths. |
| The browser cannot launch in CI. | The container lacks compatible browser binaries or system libraries, or its browser version differs from the installed Playwright package. | Use a supported Playwright CI image and align its tag with the project’s pinned version. Follow Playwright’s CI installation instructions. |
| Navigation times out or captures a blank/error page. | The app is not running, the URL is unreachable from the job, startup is incomplete, or the page depends on unavailable services. | Start the app in the job, wait for a health endpoint or readiness condition, use the job-reachable URL, and inspect network and server logs. |
| Artifacts are absent in a dedicated upload job. | The capture job did not publish the screenshot path, the upload job did not download it, or job ordering is wrong. | Declare the correct artifact path and connect the jobs with a stage dependency or needs with artifact transfer enabled. |
| The upload job fails after tests pass. | The uploader dependency was not installed, the lockfile differs, or the SDK invocation/import does not match the installed version. | Install @argos-ci/core from the project lockfile and compare the call with the current SDK reference. |
| The visual diff changes on every run. | Captured content may vary due to time, animation, asynchronous loading, fonts, data, or environment differences. | Make test data deterministic, wait for the page’s meaningful ready state, disable or stabilize motion where appropriate, and keep browser and viewport settings consistent. |
Performance, reliability, and cost considerations
- Keep capture focused. Capture the routes and states that matter rather than generating redundant screenshots. Fewer browser steps and files generally reduce job work and upload volume.
- Reuse the existing build. If tests already build the app, place capture after that build or pass a build artifact forward instead of building it again.
- Make the page deterministic. Use fixed test data and consistent viewport, browser, and fonts. Wait for the content your test needs, not an arbitrary long sleep. This reduces noisy comparisons and reruns.
- Use artifacts deliberately. A separate upload job can isolate credentials and concerns, but it adds artifact storage and another job. Set a retention period aligned with how quickly the uploader consumes screenshots.
- Choose failure behavior intentionally. A failed test or upload should be visible to maintainers. Avoid marking the visual job as allowed to fail unless that matches your review policy; doing so can hide missing visual results.
- Plan for CI variability. Browser installation, app startup, and external services can fail independently of Argos. Pin dependencies, prefer stable runners, and use bounded timeouts and readiness checks.
- Review service pricing directly. The research material here does not establish Argos pricing, quotas, or retention limits. Check its current plan information for your expected screenshot volume rather than assuming a cost.
Or skip the browser setup
If your goal is to get a clean screenshot of a deployed page rather than run framework-based visual regression tests, ScreenshotNeo is a website screenshot API and MCP server. One GET request returns an image or PDF. The examples below use the API with the ScreenshotNeo API documentation; replace the target URL and API key with your own.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
import requests
r = requests.get(
"https://api.screenshotneo.com/v1/shot",
params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"},
timeout=90,
)
r.raise_for_status()
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`Screenshot request failed: ${res.status}`);
await Bun.write("shot.webp", res);
Cookie banners are accepted like a visitor and more than 60 known consent platforms, newsletter popups, and chat widgets are removed before the screenshot; each step can be turned off. Bot checks, blank pages, timeouts, failed loads, and cache hits are not billed, with response headers reporting the page verdict and billing status. An MCP server gives AI agents tools to take screenshots, get page information, and capture PDFs. The free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 screenshots.
Create a free ScreenshotNeo account to start with 1,000 screenshots a month and no card.
FAQ
Does Argos run the browser tests for GitLab?
The pipeline runs the test framework in a GitLab job. Argos receives and compares the screenshots your test setup captures and uploads.
Can I upload screenshots from a framework other than Playwright?
Yes. The Node.js SDK can upload PNG files from a directory, so the capture framework can be separate from the uploader.
Do I need a GitLab runner?
Yes. GitLab jobs execute on runners, and a suitable active runner must be available to pick up the job.
Where should I look for current Argos GitLab behavior?
Use Argos’s current GitLab integration guide and the SDK reference. The exact review status and project configuration can change over time.


