Skip to content

Commit

Permalink
⚡ Optimize package size: Avoid bundling chrome-driver and chrome-head…
Browse files Browse the repository at this point in the history
…less-shell (#1698)
  • Loading branch information
guiyanakuang committed Aug 19, 2024
1 parent 3c8079e commit 09aaa82
Show file tree
Hide file tree
Showing 32 changed files with 936 additions and 431 deletions.
66 changes: 66 additions & 0 deletions .github/scripts/updateKnownGoodVersionsWithDownloads.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
const fs = require('fs');
const axios = require('axios');

function convertUrl(url) {
const match = url.match(/\/(\d+\.\d+\.\d+\.\d+)\/(.+)\/(.+\.zip)/);
if (match) {
const [, version, platform, filename] = match;
return `https://cdn.npmmirror.com/binaries/chrome-for-testing/${version}/${platform}/${filename}`;
}
return url;
}

function processJson(inputJson) {
const processedJson = JSON.parse(JSON.stringify(inputJson));

processedJson.versions.forEach(version => {
if (version.downloads && version.downloads.chromedriver) {
version.downloads.chromedriver.forEach(item => {
item.url = convertUrl(item.url);
});
}
if (version.downloads) {
version.downloads = { chromedriver: version.downloads.chromedriver || [] };
}
});

return processedJson;
}

async function fetchAndProcessJson() {
const url = "https://raw.githubusercontent.com/GoogleChromeLabs/chrome-for-testing/main/data/known-good-versions-with-downloads.json";

try {
console.log(`Fetching JSON from: ${url}`);
const response = await axios.get(url, { timeout: 10000 });
console.log(`Status Code: ${response.status}`);

const inputJson = response.data;
const processedJson = processJson(inputJson);

fs.writeFileSync('known-good-versions-with-downloads.json', JSON.stringify(processedJson, null, 2));
console.log("JSON processing complete. Output saved to known-good-versions-with-downloads.json");
} catch (error) {
if (error.response) {
// The request was made and the server responded with a status code that falls out of the range of 2xx
console.error(`HTTP error! status: ${error.response.status}`);
} else if (error.request) {
// The request was made but no response was received
console.error('No response received:', error.message);
} else {
// Something happened in setting up the request that triggered an Error
console.error('Error:', error.message);
}
throw error;
}
}

// If the script is run directly, execute the processing
if (require.main === module) {
fetchAndProcessJson().catch(error => {
console.error("Script failed:", error);
process.exit(1);
});
}

module.exports = { processJson, fetchAndProcessJson };
17 changes: 15 additions & 2 deletions .github/workflows/build-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,20 @@ jobs:
node-version: '16'

- name: Install dependencies
run: npm install semver fs-extra
run: npm install semver fs-extra axios

- name: Update known-good-versions-with-downloads.json
run: node .github/scripts/updateKnownGoodVersionsWithDownloads.js

- name: Upload known-good-versions-with-downloads.json
id: upload_release_app
uses: CrossPaste/oss-upload-action@main
with:
key-id: ${{ secrets.ALIYUN_ACCESSKEY_ID }}
key-secret: ${{ secrets.ALIYUN_ACCESSKEY_SECRET }}
region: oss-cn-shenzhen
bucket: crosspaste-desktop
assets: known-good-versions-with-downloads.json:known-good-versions-with-downloads.json

- name: Validate and update version
run: node .github/scripts/validateAndUpdateVersion.js
Expand Down Expand Up @@ -188,7 +201,7 @@ jobs:

- name: Upload release app
id: upload_release_app
uses: JohnGuan/oss-upload-action@main
uses: CrossPaste/oss-upload-action@main
with:
key-id: ${{ secrets.ALIYUN_ACCESSKEY_ID }}
key-secret: ${{ secrets.ALIYUN_ACCESSKEY_SECRET }}
Expand Down
4 changes: 2 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ development.properties
local.properties
local.conveyor.conf
package*.json
selenium-manager
selenium-manager.exe
!src/**/build/
build
buildSrc/build/
Expand All @@ -17,8 +19,6 @@ composeApp/GPUCache/
composeApp/build/
composeApp/dylib/
composeApp/jbr/
chrome-headless-shell-*/
chromedriver-*/
logs/
node_modules/
output*/
124 changes: 74 additions & 50 deletions composeApp/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import org.yaml.snakeyaml.Yaml
import org.yaml.snakeyaml.constructor.Constructor
import java.io.FileReader
import java.util.Properties
import java.util.zip.ZipFile

val versionProperties = Properties()
versionProperties.load(
Expand Down Expand Up @@ -265,6 +266,12 @@ compose.desktop {
}
}

val seleniumManagerJar: File =
configurations.detachedConfiguration(dependencies.create("org.seleniumhq.selenium:selenium-manager:4.23.1"))
.resolve().first()

extract(seleniumManagerJar, appResourcesRootDir.get().asFile)

// Add download info of jbr on all platforms
val jbrYamlFile = project.projectDir.toPath().resolve("jbr.yaml").toFile()
val jbrReleases = loadJbrReleases(jbrYamlFile)
Expand All @@ -273,11 +280,6 @@ compose.desktop {
jbrDir.mkdirs()
}

// Add download info of chrome-driver and chrome-headless-shell on all platforms
val webDriverProperties = Properties()
val webDriverFile = project.projectDir.toPath().resolve("webDriver.properties").toFile()
webDriverProperties.load(FileReader(webDriverFile))

if (os.isMacOsX || buildFullPlatform) {
targetFormats(TargetFormat.Dmg)

Expand Down Expand Up @@ -305,26 +307,18 @@ compose.desktop {
val result = process.inputStream.bufferedReader().use { it.readText() }.trim()

if (result == "x86_64" || buildFullPlatform) {
getAllDependencies(
getJbrReleases(
"osx-x64",
jbrReleases,
jbrDir,
webDriverProperties,
appResourcesRootDir.get(),
"osx-x64",
"mac-x64",
"macos-x64",
)
}

if (result == "arm64" || buildFullPlatform) {
getAllDependencies(
getJbrReleases(
"osx-aarch64",
jbrReleases,
jbrDir,
webDriverProperties,
appResourcesRootDir.get(),
"osx-aarch64",
"mac-arm64",
"macos-arm64",
)
}
}
Expand All @@ -337,14 +331,10 @@ compose.desktop {
val architecture = System.getProperty("os.arch")

if (architecture.contains("64")) {
getAllDependencies(
getJbrReleases(
"windows-x64",
jbrReleases,
jbrDir,
webDriverProperties,
appResourcesRootDir.get(),
"windows-x64",
"win64",
"windows-x64",
)
} else {
throw IllegalArgumentException("Unsupported architecture: $architecture")
Expand All @@ -356,14 +346,10 @@ compose.desktop {
linux {
targetFormats(TargetFormat.Deb)

getAllDependencies(
getJbrReleases(
"linux-x64",
jbrReleases,
jbrDir,
webDriverProperties,
appResourcesRootDir.get(),
"linux-x64",
"linux64",
"linux-x64",
)
}
}
Expand Down Expand Up @@ -391,27 +377,6 @@ configurations.all {
}
}

fun getAllDependencies(
jbrReleases: JbrReleases,
jbrDir: File,
webDriverProperties: Properties,
chromeDir: Directory,
jbrArch: String,
chromeArch: String,
chromeDirName: String,
) {
getJbrReleases(
jbrArch,
jbrReleases,
jbrDir,
)
getChromeDriver(
chromeArch,
webDriverProperties,
chromeDir.dir(chromeDirName),
)
}

fun getJbrReleases(
arch: String,
jbrReleases: JbrReleases,
Expand Down Expand Up @@ -484,6 +449,23 @@ fun loadJbrReleases(file: File): JbrReleases {
}
}

fun extractFile(
zip: ZipFile,
entry: java.util.zip.ZipEntry,
targetDir: Directory,
) {
val targetFile = targetDir.file(entry.name.substringAfterLast("/"))
targetFile.asFile.parentFile.mkdirs()
zip.getInputStream(entry).use { input ->
targetFile.asFile.outputStream().use { output ->
input.copyTo(output)
}
}
// Make the file executable
targetFile.asFile.setExecutable(true, false)
println("Extracted: ${targetFile.asFile.absolutePath}")
}

data class JbrReleases(
var jbr: Map<String, JbrDetails> = mutableMapOf(),
)
Expand All @@ -492,3 +474,45 @@ data class JbrDetails(
var url: String = "",
var sha512: String = "",
)

fun extract(
jar: File,
outDir: File,
) {
ZipFile(jar).use { zip ->
zip.entries().asSequence().forEach { entry ->
when (entry.name) {
"org/openqa/selenium/manager/linux/selenium-manager" -> {
extractFile(zip, entry, outDir.resolve("linux-x64"))
}
"org/openqa/selenium/manager/macos/selenium-manager" -> {
extractFile(zip, entry, outDir.resolve("macos-x64"))
extractFile(zip, entry, outDir.resolve("macos-arm64"))
}
"org/openqa/selenium/manager/windows/selenium-manager.exe" -> {
extractFile(zip, entry, outDir.resolve("windows-x64"))
}
}
}
}
}

fun extractFile(
zip: ZipFile,
entry: java.util.zip.ZipEntry,
targetDir: File,
) {
val targetFile = targetDir.resolve(entry.name.substringAfterLast("/"))
targetFile.parentFile.mkdirs()
if (!targetFile.exists() || targetFile.lastModified() < entry.lastModifiedTime.toMillis()) {
zip.getInputStream(entry).use { input ->
targetFile.outputStream().use { output ->
input.copyTo(output)
}
}
targetFile.setExecutable(true, false)
println("Extracted: ${targetFile.absolutePath}")
} else {
println("Skipped (up to date): ${targetFile.absolutePath}")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ enum class AppFileType {
USER,
LOG,
ENCRYPT,
MODULE,
DATA,
HTML,
ICON, // use for app icon
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package com.crosspaste.paste
package com.crosspaste.html

interface ChromeService {

var startSuccess: Boolean

fun html2Image(html: String): ByteArray?

fun quit()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,13 @@
package com.crosspaste.image

import com.crosspaste.utils.Loader
import okio.Path

interface ImageLoader<T, R> {
interface FaviconLoader : Loader<String, Path>

fun load(value: T): R?
}

interface FaviconLoader : ImageLoader<String, Path>

interface FileExtImageLoader : ImageLoader<Path, Path>
interface FileExtImageLoader : Loader<Path, Path>

interface ThumbnailLoader : ImageLoader<Path, Path> {
interface ThumbnailLoader : Loader<Path, Path> {

// Based on the original path, calculate the thumbnail path
fun getThumbnailPath(path: Path): Path
Expand Down
Loading

0 comments on commit 09aaa82

Please sign in to comment.