Skip to content

Commit b0685a4

Browse files
authored
feat: Add support for Podman (#459)
2 parents b18b461 + 5d39148 commit b0685a4

File tree

6 files changed

+204
-55
lines changed

6 files changed

+204
-55
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
"start": "cd examples && pnpm start",
1717
"start:prod": "cd examples && pnpm start:prod",
1818
"build": "tsc --build",
19-
"build:docker": "docker build -t visual-regression .",
19+
"build:docker": "cd visual-regression && pnpm build:docker",
2020
"watch": "tsc --build --watch",
2121
"test": "vitest",
2222
"coverage": "vitest run --coverage",

visual-regression/DOCKER.md

Lines changed: 126 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,75 +1,149 @@
11
# Visual Regression Test Docker Instructions
22

3-
The Visual Regression Tests utilize headless browsers provided by the
4-
[Playwright](https://playwright.dev/) project. Browsers tend to be very platform
5-
specific in terms of exactly how pixels end up being rendered out. The
6-
differences should be small, but they tend to be big enough such that a simple
7-
image comparison algorithm cannot reliably tell what is a real regression and
8-
what is just a platform difference.
3+
The Visual Regression Tests utilize headless browsers provided by the [Playwright](https://playwright.dev/) project. Browsers are highly platform-specific, and even small pixel differences can cause significant issues for image comparison algorithms. These differences can prevent reliable detection of regressions.
94

10-
In order to prevent this issue, the Visual Regression Tests are built to run
11-
inside a Docker container which guarantees a consistent platform environment
12-
for the given headless browser to run in.
5+
To avoid these issues, Visual Regression Tests run inside a containerized environment. This guarantees a consistent platform for headless browsers, ensuring reproducible results.
136

14-
Whenever new commits to a PR are pushed, a GitHub Action runs the Visual
15-
Regression Tests in a Linux-based Docker container to determine if the PR should
16-
be allowed to merge or not.
7+
For PRs, a GitHub Action runs these tests in a Linux-based container. Locally, you must use `--ci` mode, which launches tests in a container to produce snapshots identical to the GitHub Action environment.
178

18-
When you need to capture new snapshots or update existing ones, you must run the
19-
Visual Regression Test Runner locally in `--ci` mode. This launches the tests in
20-
a Docker container giving you exactly the same snapshot results as the tests
21-
that run in the cloud on GitHub Actions.
9+
This guide covers installing the required tools (`docker`, `colima`, or `podman`) and building the Visual Regression Test image.
2210

23-
Below are the instructions for both installing Docker and building the Visual
24-
Regression Test Image that is used when you run the tests in `--ci`.
11+
---
2512

26-
## Installing Docker
13+
## Installing a Container Runtime
2714

2815
### Mac
2916

30-
If you have a license for [Docker Desktop](https://www.docker.com/products/docker-desktop/)
31-
you can install that and all should be well. However, if you don't follow the
32-
alternative steps below:
17+
You can use Docker Desktop if you have a license. If you don’t, use Colima or Podman as alternatives.
18+
19+
#### Option 1: Docker Desktop (Requires License)
20+
21+
1. Download and install [Docker Desktop](https://www.docker.com/products/docker-desktop).
22+
2. After installation, test Docker:
23+
```bash
24+
docker ps
25+
```
26+
27+
#### Option 2: Colima (Open Source Docker Alternative)
28+
29+
1. Install the Docker CLI using [Homebrew](https://brew.sh/):
30+
```bash
31+
brew install docker
32+
```
33+
2. Install [Colima](https://colima.dev/):
34+
```bash
35+
brew install colima
36+
```
37+
3. Start Colima:
38+
```bash
39+
colima start
40+
```
41+
4. Test Docker with Colima:
42+
```bash
43+
docker ps
44+
```
45+
It should run without errors.
46+
47+
#### Option 3: Podman (Docker Alternative)
48+
49+
1. Install [Podman](https://podman.io/):
50+
```bash
51+
brew install podman
52+
```
53+
2. Start Podman:
54+
```bash
55+
podman machine init
56+
podman machine start
57+
```
58+
3. Test Podman:
59+
```bash
60+
podman ps
61+
```
62+
63+
### Linux
64+
65+
Docker is natively supported on Linux, but you can also use Podman for a rootless container environment.
66+
67+
#### Option 1: Docker
68+
69+
1. Follow the instructions for your Linux distribution to install Docker:
70+
- [Ubuntu/Debian](https://docs.docker.com/engine/install/debian/)
71+
- [Fedora/CentOS](https://docs.docker.com/engine/install/centos/)
72+
2. After installation, test Docker:
73+
```bash
74+
docker ps
75+
```
76+
77+
#### Option 2: Podman
78+
79+
1. Install [Podman](https://podman.io/) for your Linux distribution:
80+
- [Podman Installation Guide](https://podman.io/getting-started/installation)
81+
2. Test Podman:
82+
```bash
83+
podman ps
84+
```
85+
86+
### Windows
87+
88+
Windows users can use Docker Desktop if they have a license or install Podman as an alternative.
89+
90+
#### Option 1: Docker Desktop (Requires License)
91+
92+
1. Download and install [Docker Desktop](https://www.docker.com/products/docker-desktop).
93+
2. After installation, test Docker:
94+
```powershell
95+
docker ps
96+
```
97+
98+
#### Option 2: Podman (Open Source Alternative)
99+
100+
1. Install [Podman](https://podman.io/) via the Windows installer:
101+
- [Podman for Windows](https://podman.io/getting-started/installation)
102+
2. Start the Podman machine:
103+
```powershell
104+
podman machine init
105+
podman machine start
106+
```
107+
3. Test Podman:
108+
```powershell
109+
podman ps
110+
```
111+
112+
---
33113

34-
1. Using [Homebrew](https://brew.sh/) install the Docker Client:
35-
36-
```
37-
brew install docker
38-
```
114+
## Building the Test Image
39115

40-
2. Install [Colima](https://github.com/abiosoft/colima)
116+
After installing a container runtime, you must build the Visual Regression Test image.
41117

42-
```
43-
brew install colima
44-
```
118+
1. Run the build script:
45119

46-
3. Start Colima
120+
```bash
121+
pnpm build:docker
122+
```
47123

48-
```
49-
colima start
50-
```
124+
2. The script automatically detects your runtime (`docker` or `podman`) and builds the image. After a successful build, you should see the image:
51125

52-
4. Test Docker
126+
```bash
127+
docker images
128+
```
53129

54-
```
55-
docker ps
56-
```
130+
Or, if using Podman:
57131

58-
It should run without errors.
132+
```bash
133+
podman images
134+
```
59135

60-
## Building the Test Image
136+
Example output:
61137

62-
After installing Docker, you must build the Visual Regression Test Image before
63-
running the test runner in `--ci` mode.
138+
```
139+
REPOSITORY TAG IMAGE ID CREATED SIZE
140+
visual-regression latest 40476ed4acae 3 minutes ago 2.09GB
141+
```
64142

65-
```
66-
pnpm build:docker
67-
```
143+
---
68144

69-
If all goes well it should create an image called **visual-regression** locally.
145+
## References
70146

71-
```
72-
❯ docker images
73-
REPOSITORY TAG IMAGE ID CREATED SIZE
74-
visual-regression latest 40476ed4acae 3 minutes ago 2.09GB
75-
```
147+
- **Docker Desktop**: [docker.com/products/docker-desktop](https://www.docker.com/products/docker-desktop)
148+
- **Colima**: [colima.dev](https://colima.dev/)
149+
- **Podman**: [podman.io](https://podman.io/)

visual-regression/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
"build": "tsc",
1212
"build:renderer": "cd .. && pnpm build",
1313
"build:examples": "cd ../examples && pnpm build",
14-
"build:docker": "cd .. && pnpm build:docker",
14+
"build:docker": "tsc && node dist/src/build-docker.js",
1515
"serve-examples": "cd ../examples && pnpm preview:automation",
1616
"node-version": "node --version"
1717
},
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
#!/usr/bin/env ts-node
2+
3+
import { $ } from 'execa';
4+
import { argv } from 'process';
5+
import path from 'path';
6+
import { fileURLToPath } from 'url';
7+
8+
import { detectContainerRuntime } from './detectDockerRuntime.js';
9+
10+
/**
11+
* Builds a container image using the detected container runtime.
12+
* Changes the working directory to one level higher than the script's location.
13+
* @param runtime - The container runtime (`podman` or `docker`).
14+
* @param imageName - The name of the container image to build.
15+
*/
16+
async function buildContainer(
17+
runtime: string,
18+
imageName: string,
19+
): Promise<void> {
20+
// Change working directory to one level higher than the script's location
21+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
22+
const scriptDir = path.resolve(__dirname, '../../../');
23+
process.chdir(scriptDir);
24+
25+
console.log(`Working directory changed to: ${scriptDir}`);
26+
console.log(`Using ${runtime} to build the container image: ${imageName}`);
27+
try {
28+
await $({ stdio: 'inherit' })`${runtime} build -t ${imageName} .`;
29+
} catch (error) {
30+
console.error(`Failed to build the image with ${runtime}.`, error);
31+
process.exit(1);
32+
}
33+
}
34+
35+
(async () => {
36+
const imageName = argv[2] || 'visual-regression'; // Default image name
37+
try {
38+
const runtime = await detectContainerRuntime();
39+
await buildContainer(runtime, imageName);
40+
} catch (error) {
41+
if (error instanceof Error) {
42+
console.error(error.message);
43+
} else {
44+
console.error(error);
45+
}
46+
process.exit(1);
47+
}
48+
})();
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { $ } from 'execa';
2+
3+
/**
4+
* Detects the available container runtime (podman or docker).
5+
* @returns {Promise<string>} The name of the container runtime (`podman` or `docker`).
6+
* @throws {Error} If neither runtime is found.
7+
*/
8+
export async function detectContainerRuntime(): Promise<'docker' | 'podman'> {
9+
try {
10+
await $`podman -v`;
11+
return 'podman';
12+
} catch {
13+
try {
14+
await $`docker -v`;
15+
return 'docker';
16+
} catch {
17+
throw new Error(
18+
'Neither podman nor docker is installed. Please install one of them.',
19+
);
20+
}
21+
}
22+
}

visual-regression/src/index.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ import {
4545
export const certifiedSnapshotDir = 'certified-snapshots';
4646
export const failedResultsDir = 'failed-results';
4747

48+
import { detectContainerRuntime } from './detectDockerRuntime.js';
49+
4850
const browsers = { chromium };
4951
let snapshotsTested = 0;
5052
let snapshotsPassed = 0;
@@ -135,6 +137,9 @@ const argv = yargs(hideBin(process.argv))
135137
* @returns Exit code
136138
*/
137139
async function dockerCiMode(): Promise<number> {
140+
// Detect container runtime
141+
const runtime = await detectContainerRuntime();
142+
138143
// Relay the command line arguments to the docker container
139144
const commandLineStr = [
140145
argv.capture ? '--capture' : '',
@@ -149,7 +154,7 @@ async function dockerCiMode(): Promise<number> {
149154
const __dirname = path.dirname(fileURLToPath(import.meta.url));
150155
const rootDir = path.resolve(__dirname, '..', '..', '..');
151156

152-
const childProc = $({ stdio: 'inherit' })`docker run --network host \
157+
const childProc = $({ stdio: 'inherit' })`${runtime} run --network host \
153158
-v ${rootDir}:/work/ \
154159
-v /work/node_modules \
155160
-v /work/.pnpm-store \

0 commit comments

Comments
 (0)