Files
selenoid-images/build/firefox.go
T
2022-05-17 01:56:44 +03:00

229 lines
6.7 KiB
Go

package build
import (
"errors"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"strconv"
"strings"
)
const (
geckoDriverBinary = "geckodriver"
)
type Firefox struct {
SelenoidVersion string
SeleniumVersion string
Requirements
}
func (c *Firefox) Build() error {
if c.SelenoidVersion == "" && c.SeleniumVersion == "" {
return errors.New("missing Selenoid or Selenium JAR version")
}
// Build dev image
devDestDir, err := tmpDir()
if err != nil {
return fmt.Errorf("create dev temporary dir: %v", err)
}
devSrcDir := "firefox/apt"
pkgSrcPath, pkgVersion, err := c.BrowserSource.Prepare()
if err != nil {
return fmt.Errorf("invalid browser source: %v", err)
}
if pkgSrcPath != "" {
devSrcDir = "firefox/local"
pkgDestDir := filepath.Join(devDestDir, devSrcDir)
err := os.MkdirAll(pkgDestDir, 0755)
if err != nil {
return fmt.Errorf("create %v temporary dir: %v", pkgDestDir, err)
}
pkgDestPath := filepath.Join(pkgDestDir, "firefox.deb")
err = os.Rename(pkgSrcPath, pkgDestPath)
if err != nil {
return fmt.Errorf("move package: %v", err)
}
}
pkgTagVersion := extractVersion(pkgVersion)
devImageTag := fmt.Sprintf("selenoid/dev_firefox:%s", pkgTagVersion)
devImageRequirements := Requirements{NoCache: c.NoCache, Tags: []string{devImageTag}}
devImage, err := NewImage(devSrcDir, devDestDir, devImageRequirements)
if err != nil {
return fmt.Errorf("init dev image: %v", err)
}
devBuildArgs := []string{fmt.Sprintf("VERSION=%s", pkgVersion)}
devBuildArgs = append(devBuildArgs, c.channelToBuildArgs()...)
devImage.BuildArgs = devBuildArgs
if pkgSrcPath != "" {
devImage.FileServer = true
}
err = devImage.Build()
if err != nil {
return fmt.Errorf("build dev image: %v", err)
}
// Build main image
destDir, err := tmpDir()
if err != nil {
return fmt.Errorf("create temporary dir: %v", err)
}
firefoxMajorVersion, err := strconv.Atoi(majorVersion(pkgTagVersion))
geckoDriverCompatible := firefoxMajorVersion > 48
srcDir := "firefox/selenoid"
if !geckoDriverCompatible {
srcDir = "firefox/selenium"
}
image, err := NewImage(srcDir, destDir, c.Requirements)
if err != nil {
return fmt.Errorf("init dev image: %v", err)
}
image.BuildArgs = append(image.BuildArgs, fmt.Sprintf("VERSION=%s", pkgTagVersion))
firefoxMajorMinorVersion := majorMinorVersion(pkgTagVersion)
if geckoDriverCompatible {
driverVersion, err := c.downloadGeckoDriver(image.Dir)
if err != nil {
return fmt.Errorf("failed to download geckodriver: %v", err)
}
labels := []string{fmt.Sprintf("driver=geckodriver:%s", driverVersion)}
selenoidVersion, err := c.downloadSelenoid(image.Dir)
if err != nil {
return fmt.Errorf("failed to download Selenoid: %v", err)
}
labels = append(labels, fmt.Sprintf("selenoid=%s", selenoidVersion))
image.Labels = labels
browsersJsonFile := filepath.Join(image.Dir, "browsers.json")
data, err := ioutil.ReadFile(browsersJsonFile)
if err != nil {
return fmt.Errorf("failed to read browsers.json: %v", err)
}
newContents := strings.Replace(string(data), "@@VERSION@@", firefoxMajorMinorVersion, -1)
err = ioutil.WriteFile(browsersJsonFile, []byte(newContents), 0)
if err != nil {
return fmt.Errorf("failed to update browsers.json: %v", err)
}
} else {
driverVersion, err := c.downloadSeleniumJAR(image.Dir)
if err != nil {
return fmt.Errorf("failed to download Selenium JAR: %v", err)
}
image.Labels = []string{fmt.Sprintf("driver=selenium:%s", driverVersion)}
}
err = image.Build()
if err != nil {
return fmt.Errorf("build image: %v", err)
}
err = image.Test(c.TestsDir, "firefox", firefoxMajorMinorVersion)
if err != nil {
return fmt.Errorf("test image: %v", err)
}
err = image.Push()
if err != nil {
return fmt.Errorf("push image: %v", err)
}
return nil
}
func (c *Firefox) channelToBuildArgs() []string {
switch c.BrowserChannel {
case "beta":
return []string{"PPA=ppa:mozillateam/firefox-next"}
case "dev":
return []string{"PACKAGE=firefox-trunk", "PPA=ppa:ubuntu-mozilla-daily/ppa"}
case "esr":
return []string{"PACKAGE=firefox-esr", "PPA=ppa:mozillateam/ppa"}
default:
return []string{}
}
}
func (c *Firefox) downloadGeckoDriver(dir string) (string, error) {
version := c.DriverVersion
if version == LatestVersion {
v, err := latestGithubRelease("mozilla/geckodriver")
if err != nil {
return "", fmt.Errorf("latest geckodriver version: %v", err)
}
version = strings.TrimPrefix(v, "v")
}
u := fmt.Sprintf("https://github.com/mozilla/geckodriver/releases/download/v%s/geckodriver-v%s-linux64.tar.gz", version, version)
_, err := downloadDriver(u, geckoDriverBinary, dir)
if err != nil {
return "", fmt.Errorf("download geckodriver: %v", err)
}
return version, nil
}
func (c *Firefox) downloadSelenoid(dir string) (string, error) {
version := c.SelenoidVersion
if version == LatestVersion {
v, err := latestGithubRelease("aerokube/selenoid")
if err != nil {
return "", fmt.Errorf("latest Selenoid version: %v", err)
}
version = v
}
u := fmt.Sprintf("https://github.com/aerokube/selenoid/releases/download/%s/selenoid_linux_amd64", version)
data, err := downloadFile(u)
if err != nil {
return "", fmt.Errorf("download Selenoid: %v", err)
}
outputPath := filepath.Join(dir, "selenoid")
err = ioutil.WriteFile(outputPath, data, 0755)
if err != nil {
return "", fmt.Errorf("save Selenoid: %v", err)
}
return version, nil
}
func (c *Firefox) downloadSeleniumJAR(dir string) (string, error) {
version := c.SeleniumVersion
var u string
switch version {
case "2.15.0", "2.19.0", "2.20.0", "2.21.0", "2.25.0", "2.32.0", "2.35.0", "2.37.0", "2.39.0", "2.40.0", "2.41.0", "2.43.1", "2.44.0", "2.45.0", "2.48.2":
u = fmt.Sprintf("https://repo.jenkins-ci.org/releases/org/seleniumhq/selenium/selenium-server-standalone/%s/selenium-server-standalone-$selenium_version.jar", version)
case "2.47.1":
u = "http://selenium-release.storage.googleapis.com/2.47/selenium-server-standalone-2.47.1.jar"
case "2.53.1":
u = "http://selenium-release.storage.googleapis.com/2.53/selenium-server-standalone-2.53.1.jar"
case "3.2.0":
u = "http://selenium-release.storage.googleapis.com/3.2/selenium-server-standalone-3.2.0.jar"
case "3.3.1":
u = "http://selenium-release.storage.googleapis.com/3.3/selenium-server-standalone-3.3.1.jar"
case "3.4.0":
u = "https://selenium-release.storage.googleapis.com/3.4/selenium-server-standalone-3.4.0.jar"
default:
return "", fmt.Errorf("unsupported Selenium JAR version: %s", version)
}
data, err := downloadFile(u)
if err != nil {
return "", fmt.Errorf("download Selenium JAR: %v", err)
}
outputPath := filepath.Join(dir, "selenium-server-standalone.jar")
err = ioutil.WriteFile(outputPath, data, 0644)
if err != nil {
return "", fmt.Errorf("save Selenium JAR: %v", err)
}
return version, nil
}