Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ jobs:
feature: [
"browsers",
"build-essential",
"cypress-deps",
"docker-out",
"eclipse-deps",
"git-lfs",
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ Below is a list with included features, click on the link for more details.
| --- | --- |
| [browsers](./features/src/browsers/README.md) | A package which installs various browsers. |
| [build-essential](./features/src/build-essential/README.md) | Installs essential build tools (e.g., gcc, g++, make, libc-dev) for compiling C/C++ and |
| [cypress-deps](./features/src/cypress-deps/README.md) | Installs all system dependencies required for running Cypress tests in a dev container. |
| [docker-out](./features/src/docker-out/README.md) | A feature which installs the Docker client and re-uses the host socket. |
| [eclipse-deps](./features/src/eclipse-deps/README.md) | Installs all system dependencies required for running Eclipse IDE in a dev container. |
| [git-lfs](./features/src/git-lfs/README.md) | A feature which installs Git LFS. |
Expand Down
12 changes: 12 additions & 0 deletions build/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
var featureList = []string{
"browsers",
"build-essential",
"cypress-deps",
"docker-out",
"eclipse-deps",
"git-lfs",
Expand Down Expand Up @@ -82,6 +83,17 @@ func init() {
return publishFeature("build-essential")
})

////////// cypress-deps
gotaskr.Task("Feature:cypress-deps:Package", func() error {
return packageFeature("cypress-deps")
})
gotaskr.Task("Feature:cypress-deps:Test", func() error {
return testFeature("cypress-deps")
})
gotaskr.Task("Feature:cypress-deps:Publish", func() error {
return publishFeature("cypress-deps")
})

////////// docker-out
gotaskr.Task("Feature:docker-out:Package", func() error {
return packageFeature("docker-out")
Expand Down
32 changes: 32 additions & 0 deletions features/src/cypress-deps/NOTES.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
## Notes

### Cypress Binary Cache

By default, Cypress installs binaries somewhere in the user home. This directory is not a volume and therefore is cleared when the container is rebuild which means, Cypress needs to be reinstalled in each new container.

To prevent this, the Cypress cache folder can be set to a folder from the workspace which is a volume (basically the cloned repository) and with that, it does not need to be reinstalled each time the container is rebuilt.

To do this, add the following environment variable to your container:
```
"containerEnv": {
"CYPRESS_CACHE_FOLDER": "${containerWorkspaceFolder}/.cypress_cache"
}
```

Also don't forget to add `.cypress_cache` to your `.gitignore` file.

### x11 Socket

The Cypress UI in the dev-container is displayed via x11. If the corresponding socket is not correcly forwarded into the container, this can lead to heavy performance loss due to higher CPU usage.

To correctly forward the x11 socket into the container, make sure to add the following variables to the `runArgs`:
```
"runArgs": [
"-e", "DISPLAY=${localEnv:DISPLAY}",
"-v", "/tmp/.X11-unix:/tmp/.X11-unix"
]
```

### System Compatibility

Debian, Ubuntu
45 changes: 45 additions & 0 deletions features/src/cypress-deps/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# Cypress Dependencies (cypress-deps)

Installs all system dependencies required for running Cypress tests in a dev container.

## Example Usage

```json
"features": {
"ghcr.io/postfinance/devcontainer-features/cypress-deps:0.1.0": {
}
}
```

## Notes

### Cypress Binary Cache

By default, Cypress installs binaries somewhere in the user home. This directory is not a volume and therefore is cleared when the container is rebuild which means, Cypress needs to be reinstalled in each new container.

To prevent this, the Cypress cache folder can be set to a folder from the workspace which is a volume (basically the cloned repository) and with that, it does not need to be reinstalled each time the container is rebuilt.

To do this, add the following environment variable to your container:
```
"containerEnv": {
"CYPRESS_CACHE_FOLDER": "${containerWorkspaceFolder}/.cypress_cache"
}
```

Also don't forget to add `.cypress_cache` to your `.gitignore` file.

### x11 Socket

The Cypress UI in the dev-container is displayed via x11. If the corresponding socket is not correcly forwarded into the container, this can lead to heavy performance loss due to higher CPU usage.

To correctly forward the x11 socket into the container, make sure to add the following variables to the `runArgs`:
```
"runArgs": [
"-e", "DISPLAY=${localEnv:DISPLAY}",
"-v", "/tmp/.X11-unix:/tmp/.X11-unix"
]
```

### System Compatibility

Debian, Ubuntu
6 changes: 6 additions & 0 deletions features/src/cypress-deps/devcontainer-feature.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"id": "cypress-deps",
"version": "0.1.0",
"name": "Cypress Dependencies",
"description": "Installs all system dependencies required for running Cypress tests in a dev container."
}
3 changes: 3 additions & 0 deletions features/src/cypress-deps/install.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
. ./functions.sh

"./installer_$(detect_arch)"
63 changes: 63 additions & 0 deletions features/src/cypress-deps/installer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package main

import (
"builder/installer"
"fmt"
"os"
)

func main() {
if err := runMain(); err != nil {
fmt.Printf("Error: %v\n", err)
os.Exit(1)
}
}

func runMain() error {
fmt.Println("Installing Cypress Dependencies")
osInfo, err := installer.Tools.System.GetOsInfo()
if err != nil {
return fmt.Errorf("failed to get OS info: %w", err)
}

// Common dependencies for all supported distros
commonDeps := []string{
"libgbm-dev",
"libnotify-dev",
"libnss3",
"libxss1",
"libxtst6",
"xauth",
"xvfb",
}

var deps []string

debianTrixieOrNewer := osInfo.Vendor == "debian" && func() bool {
var major int
fmt.Sscanf(osInfo.VersionId, "%d", &major)
return major >= 13
}()

ubuntuNobleOrNewer := osInfo.Vendor == "ubuntu" && func() bool {
var major int
fmt.Sscanf(osInfo.VersionId, "%d", &major)
return major >= 24
}()

if debianTrixieOrNewer || ubuntuNobleOrNewer {
deps = append([]string{
"libgtk2.0-0t64",
"libgtk-3-0t64",
"libasound2t64",
}, commonDeps...)
} else {
deps = append([]string{
"libgtk2.0-0",
"libgtk-3-0",
"libasound2",
}, commonDeps...)
}

return installer.Tools.Apt.InstallDependencies(deps...)
}
26 changes: 26 additions & 0 deletions features/test/cypress-deps/packages_installed.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#!/bin/bash
set -e

[[ -f "$(dirname "$0")/../functions.sh" ]] && source "$(dirname "$0")/../functions.sh"
[[ -f "$(dirname "$0")/functions.sh" ]] && source "$(dirname "$0")/functions.sh"

# Detect distro and codename
. /etc/os-release

if { [[ "$ID" = "debian" && "$VERSION_CODENAME" = "trixie" ]] || [[ "$ID" = "ubuntu" && "$VERSION_CODENAME" = "noble" ]]; }; then
check_package_installed "libgtk2.0-0t64"
check_package_installed "libgtk-3-0t64"
check_package_installed "libasound2t64"
else
check_package_installed "libgtk2.0-0"
check_package_installed "libgtk-3-0"
check_package_installed "libasound2"
fi

check_package_installed "libgbm-dev"
check_package_installed "libnotify-dev"
check_package_installed "libnss3"
check_package_installed "libxss1"
check_package_installed "libxtst6"
check_package_installed "xauth"
check_package_installed "xvfb"
13 changes: 13 additions & 0 deletions features/test/cypress-deps/scenarios.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"packages_installed": {
"build": {
"dockerfile": "Dockerfile",
"options": [
"--add-host=host.docker.internal:host-gateway"
]
},
"features": {
"./cypress-deps": {}
}
}
}
6 changes: 6 additions & 0 deletions features/test/cypress-deps/test-images.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[
"mcr.microsoft.com/devcontainers/base:debian-12",
"mcr.microsoft.com/devcontainers/base:debian-13",
"mcr.microsoft.com/devcontainers/base:ubuntu-22.04",
"mcr.microsoft.com/devcontainers/base:ubuntu-24.04"
]
14 changes: 9 additions & 5 deletions installer/system.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,9 @@ func (s *system) MapArchitecture(mapping map[string]string) (string, error) {
}

type OsInfo struct {
Vendor string
Codename string
Vendor string
Codename string
VersionId string
}

func (s *system) GetOsInfo() (*OsInfo, error) {
Expand All @@ -38,10 +39,13 @@ func (s *system) GetOsInfo() (*OsInfo, error) {
infoMap := map[string]string{}
for scanner.Scan() {
parts := strings.SplitN(scanner.Text(), "=", 2)
infoMap[parts[0]] = parts[1]
// Remove surrounding quotes if present
val := strings.Trim(parts[1], `"`)
infoMap[parts[0]] = val
}
return &OsInfo{
Vendor: infoMap["ID"],
Codename: infoMap["VERSION_CODENAME"],
Vendor: infoMap["ID"],
Codename: infoMap["VERSION_CODENAME"],
VersionId: infoMap["VERSION_ID"],
}, nil
}