Build Script Post-Gui1 Cleanup (#9376)

This PR:
* removes much of logic related to building and packaging the gui1;
* made `./run gui` and `./run ide` work with the new gui;
* rename numerous references to the "gui2" or "new gui" in favor of simply "gui", same for "ide".
This commit is contained in:
Michał Wawrzyniec Urbańczyk 2024-03-12 20:25:51 +01:00 committed by GitHub
parent a5a729a7d6
commit d9ca6cf023
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
25 changed files with 343 additions and 1770 deletions

View File

@ -173,6 +173,55 @@ jobs:
access_token: ${{ github.token }}
permissions:
actions: write
enso-build-ci-gen-job-gui-test-linux-x86_64:
name: GUI tests (linux, x86_64)
runs-on:
- self-hosted
- Linux
steps:
- if: startsWith(runner.name, 'GitHub Actions') || startsWith(runner.name, 'Hosted Agent')
name: Setup conda (GH runners only)
uses: s-weigand/setup-conda@v1.2.1
with:
update-conda: false
conda-channels: anaconda, conda-forge
- if: startsWith(runner.name, 'GitHub Actions') || startsWith(runner.name, 'Hosted Agent')
name: Installing wasm-pack
uses: jetli/wasm-pack-action@v0.4.0
with:
version: v0.10.2
- name: Expose Artifact API and context information.
uses: actions/github-script@v7
with:
script: "\n core.exportVariable(\"ACTIONS_RUNTIME_TOKEN\", process.env[\"ACTIONS_RUNTIME_TOKEN\"])\n core.exportVariable(\"ACTIONS_RUNTIME_URL\", process.env[\"ACTIONS_RUNTIME_URL\"])\n core.exportVariable(\"GITHUB_RETENTION_DAYS\", process.env[\"GITHUB_RETENTION_DAYS\"])\n console.log(context)\n "
- name: Checking out the repository
uses: actions/checkout@v4
with:
clean: false
submodules: recursive
- name: Build Script Setup
run: ./run --help || (git clean -ffdx && ./run --help)
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- if: "(contains(github.event.pull_request.labels.*.name, 'CI: Clean build required') || inputs.clean_build_required)"
name: Clean before
run: ./run git-clean
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- run: ./run gui test
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- if: failure() && runner.os == 'Windows'
name: List files if failed (Windows)
run: Get-ChildItem -Force -Recurse
- if: failure() && runner.os != 'Windows'
name: List files if failed (non-Windows)
run: ls -lAR
- if: "(always()) && (contains(github.event.pull_request.labels.*.name, 'CI: Clean build required') || inputs.clean_build_required)"
name: Clean after
run: ./run git-clean
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
enso-build-ci-gen-job-lint-linux-x86_64:
name: Lint (linux, x86_64)
runs-on:
@ -223,7 +272,7 @@ jobs:
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
enso-build-ci-gen-job-native-test-linux-x86_64:
name: Native GUI tests (linux, x86_64)
name: Native Rust tests (linux, x86_64)
runs-on:
- self-hosted
- Linux
@ -272,7 +321,7 @@ jobs:
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
enso-build-ci-gen-job-new-gui-build-linux-x86_64:
name: New (Vue) GUI build (linux, x86_64)
name: GUI build (linux, x86_64)
runs-on:
- self-hosted
- Linux
@ -306,7 +355,7 @@ jobs:
run: ./run git-clean
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- run: ./run gui2 build
- run: ./run gui build
env:
ENSO_CLOUD_API_URL: ${{ vars.ENSO_CLOUD_API_URL }}
ENSO_CLOUD_CHAT_URL: ${{ vars.ENSO_CLOUD_CHAT_URL }}
@ -331,7 +380,7 @@ jobs:
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
enso-build-ci-gen-job-new-gui-build-macos-x86_64:
name: New (Vue) GUI build (macos, x86_64)
name: GUI build (macos, x86_64)
runs-on:
- macos-latest
steps:
@ -364,7 +413,7 @@ jobs:
run: ./run git-clean
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- run: ./run gui2 build
- run: ./run gui build
env:
ENSO_CLOUD_API_URL: ${{ vars.ENSO_CLOUD_API_URL }}
ENSO_CLOUD_CHAT_URL: ${{ vars.ENSO_CLOUD_CHAT_URL }}
@ -389,7 +438,7 @@ jobs:
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
enso-build-ci-gen-job-new-gui-build-windows-x86_64:
name: New (Vue) GUI build (windows, x86_64)
name: GUI build (windows, x86_64)
runs-on:
- self-hosted
- Windows
@ -423,7 +472,7 @@ jobs:
run: ./run git-clean
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- run: ./run gui2 build
- run: ./run gui build
env:
ENSO_CLOUD_API_URL: ${{ vars.ENSO_CLOUD_API_URL }}
ENSO_CLOUD_CHAT_URL: ${{ vars.ENSO_CLOUD_CHAT_URL }}
@ -447,56 +496,7 @@ jobs:
run: ./run git-clean
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
enso-build-ci-gen-job-new-gui-test-linux-x86_64:
name: New (Vue) GUI tests (linux, x86_64)
runs-on:
- self-hosted
- Linux
steps:
- if: startsWith(runner.name, 'GitHub Actions') || startsWith(runner.name, 'Hosted Agent')
name: Setup conda (GH runners only)
uses: s-weigand/setup-conda@v1.2.1
with:
update-conda: false
conda-channels: anaconda, conda-forge
- if: startsWith(runner.name, 'GitHub Actions') || startsWith(runner.name, 'Hosted Agent')
name: Installing wasm-pack
uses: jetli/wasm-pack-action@v0.4.0
with:
version: v0.10.2
- name: Expose Artifact API and context information.
uses: actions/github-script@v7
with:
script: "\n core.exportVariable(\"ACTIONS_RUNTIME_TOKEN\", process.env[\"ACTIONS_RUNTIME_TOKEN\"])\n core.exportVariable(\"ACTIONS_RUNTIME_URL\", process.env[\"ACTIONS_RUNTIME_URL\"])\n core.exportVariable(\"GITHUB_RETENTION_DAYS\", process.env[\"GITHUB_RETENTION_DAYS\"])\n console.log(context)\n "
- name: Checking out the repository
uses: actions/checkout@v4
with:
clean: false
submodules: recursive
- name: Build Script Setup
run: ./run --help || (git clean -ffdx && ./run --help)
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- if: "(contains(github.event.pull_request.labels.*.name, 'CI: Clean build required') || inputs.clean_build_required)"
name: Clean before
run: ./run git-clean
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- run: ./run gui2 test
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- if: failure() && runner.os == 'Windows'
name: List files if failed (Windows)
run: Get-ChildItem -Force -Recurse
- if: failure() && runner.os != 'Windows'
name: List files if failed (non-Windows)
run: ls -lAR
- if: "(always()) && (contains(github.event.pull_request.labels.*.name, 'CI: Clean build required') || inputs.clean_build_required)"
name: Clean after
run: ./run git-clean
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
enso-build-ci-gen-job-package-new-ide-linux-x86_64:
enso-build-ci-gen-job-package-ide-linux-x86_64:
name: Package New IDE (linux, x86_64)
needs:
- enso-build-ci-gen-job-build-backend-linux-x86_64
@ -533,7 +533,7 @@ jobs:
run: ./run git-clean
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- run: ./run ide2 build --backend-source current-ci-run --gui2-upload-artifact false
- run: ./run ide build --backend-source current-ci-run --gui-upload-artifact false
env:
ENSO_CLOUD_API_URL: ${{ vars.ENSO_CLOUD_API_URL }}
ENSO_CLOUD_CHAT_URL: ${{ vars.ENSO_CLOUD_CHAT_URL }}
@ -557,7 +557,7 @@ jobs:
run: ./run git-clean
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
enso-build-ci-gen-job-package-new-ide-macos-x86_64:
enso-build-ci-gen-job-package-ide-macos-x86_64:
name: Package New IDE (macos, x86_64)
needs:
- enso-build-ci-gen-job-build-backend-macos-x86_64
@ -599,7 +599,7 @@ jobs:
run: npm uninstall --save --workspace enso electron-builder
- name: Install new Electron Builder
run: npm install --save-dev --workspace enso electron-builder@24.6.4
- run: ./run ide2 build --backend-source current-ci-run --gui2-upload-artifact false
- run: ./run ide build --backend-source current-ci-run --gui-upload-artifact false
env:
APPLEID: ${{ secrets.APPLE_NOTARIZATION_USERNAME }}
APPLEIDPASS: ${{ secrets.APPLE_NOTARIZATION_PASSWORD }}
@ -630,7 +630,7 @@ jobs:
run: ./run git-clean
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
enso-build-ci-gen-job-package-new-ide-windows-x86_64:
enso-build-ci-gen-job-package-ide-windows-x86_64:
name: Package New IDE (windows, x86_64)
needs:
- enso-build-ci-gen-job-build-backend-windows-x86_64
@ -667,7 +667,7 @@ jobs:
run: ./run git-clean
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- run: ./run ide2 build --backend-source current-ci-run --gui2-upload-artifact false
- run: ./run ide build --backend-source current-ci-run --gui-upload-artifact false
env:
ENSO_CLOUD_API_URL: ${{ vars.ENSO_CLOUD_API_URL }}
ENSO_CLOUD_CHAT_URL: ${{ vars.ENSO_CLOUD_CHAT_URL }}
@ -694,7 +694,7 @@ jobs:
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
enso-build-ci-gen-job-wasm-test-linux-x86_64:
name: WASM GUI tests (linux, x86_64)
name: WASM tests (linux, x86_64)
runs-on:
- self-hosted
- Linux

View File

@ -273,10 +273,10 @@ jobs:
name: Publish release (linux, x86_64)
needs:
- enso-build-ci-gen-draft-release-linux-x86_64
- enso-build-ci-gen-upload-ide2-linux-x86_64
- enso-build-ci-gen-upload-ide2-macos-aarch64
- enso-build-ci-gen-upload-ide2-macos-x86_64
- enso-build-ci-gen-upload-ide2-windows-x86_64
- enso-build-ci-gen-upload-ide-linux-x86_64
- enso-build-ci-gen-upload-ide-macos-aarch64
- enso-build-ci-gen-upload-ide-macos-x86_64
- enso-build-ci-gen-upload-ide-windows-x86_64
runs-on:
- self-hosted
- Linux
@ -330,8 +330,8 @@ jobs:
AWS_SECRET_ACCESS_KEY: ${{ secrets.ARTEFACT_S3_SECRET_ACCESS_KEY }}
ENSO_RELEASE_ID: ${{ needs.enso-build-ci-gen-draft-release-linux-x86_64.outputs.ENSO_RELEASE_ID }}
ENSO_VERSION: ${{ needs.enso-build-ci-gen-draft-release-linux-x86_64.outputs.ENSO_VERSION }}
enso-build-ci-gen-upload-ide2-linux-x86_64:
name: Build New IDE (linux, x86_64)
enso-build-ci-gen-upload-ide-linux-x86_64:
name: Build IDE (linux, x86_64)
needs:
- enso-build-ci-gen-draft-release-linux-x86_64
- enso-build-ci-gen-job-upload-backend-linux-x86_64
@ -368,7 +368,7 @@ jobs:
run: ./run git-clean
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- run: ./run ide2 upload --backend-source release --backend-release ${{env.ENSO_RELEASE_ID}}
- run: ./run ide upload --backend-source release --backend-release ${{env.ENSO_RELEASE_ID}}
env:
ENSO_CLOUD_API_URL: ${{ vars.ENSO_CLOUD_API_URL }}
ENSO_CLOUD_CHAT_URL: ${{ vars.ENSO_CLOUD_CHAT_URL }}
@ -395,8 +395,8 @@ jobs:
env:
ENSO_RELEASE_ID: ${{ needs.enso-build-ci-gen-draft-release-linux-x86_64.outputs.ENSO_RELEASE_ID }}
ENSO_VERSION: ${{ needs.enso-build-ci-gen-draft-release-linux-x86_64.outputs.ENSO_VERSION }}
enso-build-ci-gen-upload-ide2-macos-aarch64:
name: Build New IDE (macos, aarch64)
enso-build-ci-gen-upload-ide-macos-aarch64:
name: Build IDE (macos, aarch64)
needs:
- enso-build-ci-gen-draft-release-linux-x86_64
- enso-build-ci-gen-job-upload-backend-macos-aarch64
@ -440,7 +440,7 @@ jobs:
run: npm uninstall --save --workspace enso electron-builder
- name: Install new Electron Builder
run: npm install --save-dev --workspace enso electron-builder@24.6.4
- run: ./run ide2 upload --backend-source release --backend-release ${{env.ENSO_RELEASE_ID}}
- run: ./run ide upload --backend-source release --backend-release ${{env.ENSO_RELEASE_ID}}
env:
APPLEID: ${{ secrets.APPLE_NOTARIZATION_USERNAME }}
APPLEIDPASS: ${{ secrets.APPLE_NOTARIZATION_PASSWORD }}
@ -474,8 +474,8 @@ jobs:
env:
ENSO_RELEASE_ID: ${{ needs.enso-build-ci-gen-draft-release-linux-x86_64.outputs.ENSO_RELEASE_ID }}
ENSO_VERSION: ${{ needs.enso-build-ci-gen-draft-release-linux-x86_64.outputs.ENSO_VERSION }}
enso-build-ci-gen-upload-ide2-macos-x86_64:
name: Build New IDE (macos, x86_64)
enso-build-ci-gen-upload-ide-macos-x86_64:
name: Build IDE (macos, x86_64)
needs:
- enso-build-ci-gen-draft-release-linux-x86_64
- enso-build-ci-gen-job-upload-backend-macos-x86_64
@ -517,7 +517,7 @@ jobs:
run: npm uninstall --save --workspace enso electron-builder
- name: Install new Electron Builder
run: npm install --save-dev --workspace enso electron-builder@24.6.4
- run: ./run ide2 upload --backend-source release --backend-release ${{env.ENSO_RELEASE_ID}}
- run: ./run ide upload --backend-source release --backend-release ${{env.ENSO_RELEASE_ID}}
env:
APPLEID: ${{ secrets.APPLE_NOTARIZATION_USERNAME }}
APPLEIDPASS: ${{ secrets.APPLE_NOTARIZATION_PASSWORD }}
@ -551,8 +551,8 @@ jobs:
env:
ENSO_RELEASE_ID: ${{ needs.enso-build-ci-gen-draft-release-linux-x86_64.outputs.ENSO_RELEASE_ID }}
ENSO_VERSION: ${{ needs.enso-build-ci-gen-draft-release-linux-x86_64.outputs.ENSO_VERSION }}
enso-build-ci-gen-upload-ide2-windows-x86_64:
name: Build New IDE (windows, x86_64)
enso-build-ci-gen-upload-ide-windows-x86_64:
name: Build IDE (windows, x86_64)
needs:
- enso-build-ci-gen-draft-release-linux-x86_64
- enso-build-ci-gen-job-upload-backend-windows-x86_64
@ -589,7 +589,7 @@ jobs:
run: ./run git-clean
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- run: ./run ide2 upload --backend-source release --backend-release ${{env.ENSO_RELEASE_ID}}
- run: ./run ide upload --backend-source release --backend-release ${{env.ENSO_RELEASE_ID}}
env:
ENSO_CLOUD_API_URL: ${{ vars.ENSO_CLOUD_API_URL }}
ENSO_CLOUD_CHAT_URL: ${{ vars.ENSO_CLOUD_CHAT_URL }}

View File

@ -1,5 +1,5 @@
/** @file THIS SCRIPT IS PROVIDED ONLY FOR CONVENIENCE.
* The sources of truth are at `build/build/src/project/gui2.rs` and
* The sources of truth are at `build/build/src/project/gui.rs` and
* `build/build/src/ide/web/fonts.rs`. */
import * as fsSync from 'node:fs'

View File

@ -68,22 +68,13 @@ Artifacts are platform specific and consist of the single image file.
### GUI
GUI is the front-end part of the project. It consists of `WASM` target.
Sources consist mostly of TS code for the web page that embeds the `WASM`
binaries.
GUI is the front-end part of the project. It also packages WASM-compiled parser
written in rust.
Artifacts are portable across the platforms and consist of the web page that can
be served either using Electron client (as IDE does) or using a web server (like
the Cloud version of Enso).
### WASM
This is the core of GUI, written in Rust. It has no external dependencies.
Artifacts are portable across the platforms and consist of the single WASM
binary accompanied by the JS snippets and glue.
### Backend
Backend is the back-end part of the project, as seen from the IDE perspective.

View File

@ -63,15 +63,6 @@
type: project_manager_bundle
var: project_manager_bundle
dist/:
gui/:
assets/:
dynamic-assets/: # Assets used by the WASM application.
pkg.js: # The `pkg.js` artifact of wasm-pack WITH bundled snippets.
pkg.js.map: # The sourcemap mapping to `pkg.js` generated by wasm-pack.
pkg-opt.wasm: # The optimized WASM artifact.
entrypoint.js:
style.css:
gui2/:
assets/:

View File

@ -15,10 +15,10 @@ Enso IDE is the main product of the Enso project. The packages are stand-alone,
Download links:
- [Linux]({{download_prefix}}/ide2-enso-linux-x86_64-{{version}}.AppImage) (AppImage);
- [macOS (x64)]({{download_prefix}}/ide2-enso-mac-x64-{{version}}.dmg) (DMG);
- [macOS (arm64)]({{download_prefix}}/ide2-enso-mac-arm64-{{version}}.dmg) (DMG);
- [Windows]({{download_prefix}}/ide2-enso-win-x64-{{version}}.exe) (Installer Executable).
- [Linux]({{download_prefix}}/enso-linux-x86_64-{{version}}.AppImage) (AppImage);
- [macOS (x64)]({{download_prefix}}/enso-mac-x64-{{version}}.dmg) (DMG);
- [macOS (arm64)]({{download_prefix}}/enso-mac-arm64-{{version}}.dmg) (DMG);
- [Windows]({{download_prefix}}/enso-win-x64-{{version}}.exe) (Installer Executable).
This is the recommended download for most users.

View File

@ -402,16 +402,16 @@ impl JobArchetype for PublishRelease {
/// Build new IDE and upload it as a release asset.
#[derive(Clone, Copy, Debug)]
pub struct UploadIde2;
pub struct UploadIde;
impl JobArchetype for UploadIde2 {
impl JobArchetype for UploadIde {
fn job(&self, target: Target) -> Job {
RunStepsBuilder::new(
"ide2 upload --backend-source release --backend-release ${{env.ENSO_RELEASE_ID}}",
"ide upload --backend-source release --backend-release ${{env.ENSO_RELEASE_ID}}",
)
.cleaning(RELEASE_CLEANING_POLICY)
.customize(with_packaging_steps(target.0))
.build_job("Build New IDE", target)
.build_job("Build IDE", target)
}
}
@ -483,9 +483,9 @@ fn add_release_steps(workflow: &mut Workflow) -> Result {
for target in RELEASE_TARGETS {
let backend_job_id = workflow.add_dependent(target, job::UploadBackend, [&prepare_job_id]);
let build_ide2_job_id =
workflow.add_dependent(target, UploadIde2, [&prepare_job_id, &backend_job_id]);
packaging_job_ids.push(build_ide2_job_id.clone());
let build_ide_job_id =
workflow.add_dependent(target, UploadIde, [&prepare_job_id, &backend_job_id]);
packaging_job_ids.push(build_ide_job_id.clone());
}
let publish_deps = {
@ -587,7 +587,7 @@ pub fn gui() -> Result<Workflow> {
workflow.add(PRIMARY_TARGET, job::Lint);
workflow.add(PRIMARY_TARGET, job::WasmTest);
workflow.add(PRIMARY_TARGET, job::NativeTest);
workflow.add(PRIMARY_TARGET, job::NewGuiTest);
workflow.add(PRIMARY_TARGET, job::GuiTest);
// FIXME: Integration tests are currently always failing.
// The should be reinstated when fixed.
@ -597,7 +597,7 @@ pub fn gui() -> Result<Workflow> {
for target in CHECKED_TARGETS {
let project_manager_job = workflow.add(target, job::BuildBackend);
workflow.add_customized(target, job::PackageNewIde, |job| {
workflow.add_customized(target, job::PackageIde, |job| {
job.needs.insert(project_manager_job.clone());
});
workflow.add(target, job::NewGuiBuild);

View File

@ -264,16 +264,16 @@ pub struct NativeTest;
impl JobArchetype for NativeTest {
fn job(&self, target: Target) -> Job {
plain_job(target, "Native GUI tests", "wasm test --no-wasm")
plain_job(target, "Native Rust tests", "wasm test --no-wasm")
}
}
#[derive(Clone, Copy, Debug)]
pub struct NewGuiTest;
pub struct GuiTest;
impl JobArchetype for NewGuiTest {
impl JobArchetype for GuiTest {
fn job(&self, target: Target) -> Job {
plain_job(target, "New (Vue) GUI tests", "gui2 test")
plain_job(target, "GUI tests", "gui test")
}
}
@ -283,10 +283,10 @@ pub struct NewGuiBuild;
impl JobArchetype for NewGuiBuild {
fn job(&self, target: Target) -> Job {
let command = "gui2 build";
let command = "gui build";
RunStepsBuilder::new(command)
.customize(|step| vec![expose_cloud_vars(step)])
.build_job("New (Vue) GUI build", target)
.build_job("GUI build", target)
}
}
@ -295,7 +295,7 @@ pub struct WasmTest;
impl JobArchetype for WasmTest {
fn job(&self, target: Target) -> Job {
plain_job(target, "WASM GUI tests", "wasm test --no-native")
plain_job(target, "WASM tests", "wasm test --no-native")
}
}
@ -312,18 +312,6 @@ impl JobArchetype for IntegrationTest {
}
}
#[derive(Clone, Copy, Debug)]
pub struct BuildWasm;
impl JobArchetype for BuildWasm {
fn job(&self, target: Target) -> Job {
let command = "wasm build --wasm-upload-artifact ${{ runner.os == 'Linux' }}";
RunStepsBuilder::new(command)
.customize(|step| vec![step.with_secret_exposed(crate::env::ENSO_AG_GRID_LICENSE_KEY)])
.build_job("Build GUI (WASM)", target)
}
}
#[derive(Clone, Copy, Debug)]
pub struct BuildBackend;
@ -447,12 +435,12 @@ pub fn with_packaging_steps(os: OS) -> impl FnOnce(Step) -> Vec<Step> {
}
#[derive(Clone, Copy, Debug)]
pub struct PackageNewIde;
pub struct PackageIde;
impl JobArchetype for PackageNewIde {
impl JobArchetype for PackageIde {
fn job(&self, target: Target) -> Job {
RunStepsBuilder::new(
"ide2 build --backend-source current-ci-run --gui2-upload-artifact false",
"ide build --backend-source current-ci-run --gui-upload-artifact false",
)
.customize(with_packaging_steps(target.0))
.build_job("Package New IDE", target)

View File

@ -1,6 +1,5 @@
use crate::prelude::*;
use byte_unit::Byte;
use ide_ci::program;
use ide_ci::programs;
use semver::VersionReq;
@ -49,7 +48,6 @@ impl RecognizedProgram {
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
#[serde(rename_all = "kebab-case")]
pub struct ConfigRaw {
pub wasm_size_limit: Option<String>,
pub required_versions: HashMap<String, String>,
}
@ -58,7 +56,6 @@ pub struct ConfigRaw {
/// In our case, it is usually a configuration file in the main repository.
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
pub struct Config {
pub wasm_size_limit: Option<Byte>,
pub required_versions: HashMap<RecognizedProgram, VersionReq>,
}
@ -90,13 +87,7 @@ impl TryFrom<ConfigRaw> for Config {
);
}
Ok(Self {
wasm_size_limit: value
.wasm_size_limit
.map(|limit_text| <Byte as FromString>::from_str(&limit_text))
.transpose()?,
required_versions,
})
Ok(Self { required_versions })
}
}

View File

@ -3,22 +3,16 @@ use crate::prelude::*;
use crate::ide::web::env::CSC_KEY_PASSWORD;
use crate::paths::generated;
use crate::project::gui::BuildInfo;
use crate::project::wasm;
use crate::project::IsArtifact;
use crate::project::ProcessWrapper;
use anyhow::Context;
use futures_util::future::try_join;
use futures_util::future::try_join3;
use ide_ci::io::download_all;
use ide_ci::ok_ready_boxed;
use ide_ci::program::command::FallibleManipulator;
use ide_ci::programs::node::NpmCommand;
use ide_ci::programs::Npm;
use std::process::Stdio;
use tempfile::TempDir;
use tokio::process::Child;
use tracing::Span;
// ==============
@ -199,52 +193,6 @@ pub enum Command {
Watch,
}
/// Things that are common to `watch` and `build`.
#[derive(Debug)]
pub struct ContentEnvironment<Assets, Output> {
pub asset_dir: Assets,
pub wasm: wasm::Artifact,
pub output_path: Output,
}
impl<Output: AsRef<Path>> ContentEnvironment<TempDir, Output> {
pub async fn new(
ide: &IdeDesktop,
wasm: impl Future<Output = Result<wasm::Artifact>>,
build_info: &BuildInfo,
output_path: Output,
) -> Result<Self> {
crate::web::install(&ide.repo_root).await?;
let asset_dir = TempDir::new()?;
let assets_download = download_js_assets(&asset_dir);
let fonts_download = fonts::install_html_fonts(&ide.cache, &ide.octocrab, &asset_dir);
let (wasm, _, _) = try_join3(wasm, assets_download, fonts_download).await?;
ide.write_build_info(build_info)?;
Ok(ContentEnvironment { asset_dir, wasm, output_path })
}
}
impl<Assets: AsRef<Path>, Output: AsRef<Path>> FallibleManipulator
for ContentEnvironment<Assets, Output>
{
fn try_applying<C: IsCommandWrapper + ?Sized>(&self, command: &mut C) -> Result {
let artifacts_for_gui =
self.wasm.files_to_ship().into_iter().map(|file| file.to_path_buf()).collect_vec();
command
.set_env(env::ENSO_BUILD_GUI, self.output_path.as_ref())?
.set_env(env::ENSO_BUILD_GUI_WASM_ARTIFACTS, &artifacts_for_gui)?
.set_env(env::ENSO_BUILD_GUI_ASSETS, self.asset_dir.as_ref())?;
Ok(())
}
}
impl<Assets, Output> Drop for ContentEnvironment<Assets, Output> {
fn drop(&mut self) {
info!("Dropping content environment.")
}
}
pub fn target_os_flag(os: OS) -> Result<&'static str> {
match os {
OS::Windows => Ok("--win"),
@ -332,51 +280,6 @@ impl IdeDesktop {
Ok(IconsArtifacts(output_path.as_ref().into()))
}
#[tracing::instrument(name="Building IDE Content.", skip_all, fields(
dest = %output_path.as_ref().display(),
build_info,
err))]
pub async fn build_content<P: AsRef<Path>>(
&self,
wasm: impl Future<Output = Result<wasm::Artifact>>,
build_info: &BuildInfo,
output_path: P,
) -> Result<ContentEnvironment<TempDir, P>> {
let env = ContentEnvironment::new(self, wasm, build_info, output_path).await?;
self.npm()?
.try_applying(&env)?
.workspace(Workspaces::Content)
.run("build")
.run_ok()
.await?;
Ok(env)
}
#[tracing::instrument(name="Setting up GUI Content watcher.",
fields(wasm = tracing::field::Empty),
err)]
pub async fn watch_content(
&self,
wasm: impl Future<Output = Result<wasm::Artifact>>,
build_info: &BuildInfo,
) -> Result<Watcher> {
// When watching we expect our artifacts to be served through server, not appear in any
// specific location on the disk.
let output_path = TempDir::new()?;
let watch_environment =
ContentEnvironment::new(self, wasm, build_info, output_path).await?;
Span::current().record("wasm", watch_environment.wasm.as_ref().as_str());
let child_process = self
.npm()?
.try_applying(&watch_environment)?
.workspace(Workspaces::Content)
.run("watch")
.spawn_intercepting()?;
Ok(Watcher { child_process, watch_environment })
}
/// Build the full Electron package, using the electron-builder.
#[tracing::instrument(name="Preparing distribution of the IDE.", skip_all, fields(
dest = %output_path.as_ref().display(),
@ -458,68 +361,6 @@ impl IdeDesktop {
Ok(())
}
/// Spawn the watch script for the client.
pub async fn watch(
&self,
wasm_watch_job: BoxFuture<
'static,
Result<crate::project::PerhapsWatched<crate::project::Wasm>>,
>,
build_info: BoxFuture<'static, Result<BuildInfo>>,
get_project_manager: BoxFuture<'static, Result<crate::project::backend::Artifact>>,
ide_options: Vec<String>,
) -> Result {
let npm_install_job = crate::web::install(&self.repo_root);
// TODO: This could be possibly optimized by awaiting WASM a bit later, and passing its
// future to the ContentEnvironment. However, the code would get a little tricky.
// Should be reconsidered in the future, based on actual timings.
let (_npm_installed, watched_wasm, project_manager) =
try_join!(npm_install_job, wasm_watch_job, get_project_manager)?;
let pm_bundle = ProjectManagerInfo::new(&project_manager)?;
let temp_dir_for_gui = TempDir::new()?;
let content_env = ContentEnvironment::new(
self,
ok_ready_boxed(watched_wasm.as_ref().clone()),
&build_info.await?,
&temp_dir_for_gui,
)
.await?;
let mut script_args = Vec::new();
if !ide_options.is_empty() {
script_args.push("--");
script_args.extend(ide_options.iter().map(String::as_str));
}
let temp_dir_for_ide = TempDir::new()?;
self.npm()?
.try_applying(&content_env)?
.set_env(env::ENSO_BUILD_IDE, temp_dir_for_ide.path())?
.try_applying(&pm_bundle)?
.workspace(Workspaces::Enso)
.run("watch")
.args(script_args)
.run_ok()
.await?;
Ok(())
}
}
#[derive(Debug)]
pub struct Watcher {
pub watch_environment: ContentEnvironment<TempDir, TempDir>,
pub child_process: Child,
}
impl ProcessWrapper for Watcher {
fn inner(&mut self) -> &mut Child {
&mut self.child_process
}
}
#[cfg(test)]

View File

@ -27,18 +27,13 @@ use octocrab::models::repos::Asset;
pub mod backend;
pub mod engine;
pub mod gui;
pub mod gui2;
pub mod ide;
pub mod ide2;
pub mod project_manager;
pub mod runtime;
pub mod wasm;
pub use backend::Backend;
pub use gui::Gui;
pub use ide::Ide;
pub use runtime::Runtime;
pub use wasm::Wasm;

View File

@ -1,28 +1,132 @@
//! Build logic for the GUI project.
//!
//! The GUI is Vue.js-based and located under `app/gui2`.
use crate::prelude::*;
use crate::ide::web::IdeDesktop;
use crate::project::perhaps_watch;
use crate::paths::generated::RepoRootAppGui2Dist;
use crate::paths::generated::RepoRootDistGui2Assets;
use crate::project::Context;
use crate::project::IsArtifact;
use crate::project::IsTarget;
use crate::project::IsWatchable;
use crate::project::IsWatcher;
use crate::project::PerhapsWatched;
use crate::project::Wasm;
use crate::source::BuildSource;
use crate::source::GetTargetJob;
use crate::source::WatchTargetJob;
use crate::source::WithDestination;
use crate::BoxFuture;
use derivative::Derivative;
use futures_util::future::try_join;
use ide_ci::ok_ready_boxed;
use ide_ci::programs::node::NpmCommand;
use ide_ci::programs::Npm;
// ===============
// === Scripts ===
// ===============
/// The scripts defined in `package.json`.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, strum::AsRefStr)]
#[strum(serialize_all = "kebab-case")]
pub enum Scripts {
Dev,
Build,
Preview,
Test,
#[strum(serialize = "test:unit")]
TestUnit,
#[strum(serialize = "test:e2e")]
TestE2e,
BuildOnly,
TypeCheck,
Lint,
Format,
BuildRustFfi,
}
pub fn script(repo_root: impl AsRef<Path>, script: Scripts) -> Result<NpmCommand> {
let mut ret = Npm.cmd()?;
ret.current_dir(repo_root).workspace(crate::web::Workspace::EnsoGui2).run(script.as_ref());
Ok(ret)
}
pub fn dashboard_script(repo_root: impl AsRef<Path>, script: Scripts) -> Result<NpmCommand> {
let mut ret = Npm.cmd()?;
ret.current_dir(repo_root).workspace(crate::web::Workspace::EnsoDashboard).run(script.as_ref());
Ok(ret)
}
// ================
// === Commands ===
// ================
/// Run steps that should be done along with the "lint"
pub fn lint(repo_root: impl AsRef<Path>) -> BoxFuture<'static, Result> {
install_and_run_script(Scripts::Lint, repo_root)
}
pub fn tests(repo_root: impl AsRef<Path>) -> BoxFuture<'static, Result> {
install_and_run_script(Scripts::Test, repo_root)
}
pub fn dashboard_tests(repo_root: impl AsRef<Path>) -> BoxFuture<'static, Result> {
install_and_run_dashboard_script(Scripts::Test, repo_root)
}
/// Run unit tests.
pub fn unit_tests(repo_root: impl AsRef<Path>) -> BoxFuture<'static, Result> {
install_and_run_script(Scripts::TestUnit, repo_root)
}
/// Run dashboard unit tests.
pub fn dashboard_unit_tests(repo_root: impl AsRef<Path>) -> BoxFuture<'static, Result> {
install_and_run_dashboard_script(Scripts::TestUnit, repo_root)
}
/// Run E2E tests.
pub fn e2e_tests(repo_root: impl AsRef<Path>) -> BoxFuture<'static, Result> {
install_and_run_script(Scripts::TestE2e, repo_root)
}
/// Run dashboard E2E tests.
pub fn dashboard_e2e_tests(repo_root: impl AsRef<Path>) -> BoxFuture<'static, Result> {
install_and_run_dashboard_script(Scripts::TestE2e, repo_root)
}
pub fn watch(repo_root: impl AsRef<Path>) -> BoxFuture<'static, Result> {
install_and_run_script(Scripts::Dev, repo_root)
}
fn install_and_run_script(
script: Scripts,
repo_root: impl AsRef<Path>,
) -> BoxFuture<'static, Result> {
let repo_root = repo_root.as_ref().to_owned();
async move {
crate::web::install(&repo_root).await?;
self::script(&repo_root, script)?.run_ok().await
}
.boxed()
}
fn install_and_run_dashboard_script(
script: Scripts,
repo_root: impl AsRef<Path>,
) -> BoxFuture<'static, Result> {
let repo_root = repo_root.as_ref().to_owned();
async move {
crate::web::install(&repo_root).await?;
dashboard_script(&repo_root, script)?.run_ok().await
}
.boxed()
}
// ================
// === Artifact ===
// ================
/// The [artifact](IsArtifact) for the new GUI.
#[derive(Clone, Debug, PartialEq, Eq, Hash, Deref)]
pub struct Artifact(crate::paths::generated::RepoRootDistGui);
pub struct Artifact(pub RepoRootAppGui2Dist);
impl AsRef<Path> for Artifact {
fn as_ref(&self) -> &Path {
@ -33,84 +137,27 @@ impl AsRef<Path> for Artifact {
impl IsArtifact for Artifact {}
impl Artifact {
pub fn new(gui_path: impl AsRef<Path>) -> Self {
// TODO: sanity check
Self(crate::paths::generated::RepoRootDistGui::new_root(gui_path.as_ref()))
pub fn new(path: impl AsRef<Path>) -> Self {
Artifact(RepoRootAppGui2Dist::new_root(path.as_ref()))
}
}
#[derive(Clone, Derivative, derive_more::Deref)]
#[derivative(Debug)]
pub struct WatchInput {
#[deref]
pub wasm: <Wasm as IsWatchable>::WatchInput,
}
#[derive(derivative::Derivative)]
#[derivative(Debug)]
pub struct BuildInput {
#[derivative(Debug = "ignore")]
pub wasm: GetTargetJob<Wasm>,
/// BoxFuture<'static, Result<wasm::Artifact>>,
#[derivative(Debug = "ignore")]
pub build_info: BoxFuture<'static, Result<BuildInfo>>,
}
/// Watcher of the GUI (including WASM watcher).
#[derive(Debug)]
pub struct Watcher {
/// WASM watcher.
pub wasm: PerhapsWatched<Wasm>,
/// Watcher of the content project.
pub web: crate::project::Watcher<Gui, crate::ide::web::Watcher>,
}
impl AsRef<Artifact> for Watcher {
fn as_ref(&self) -> &Artifact {
&self.web.artifact
}
}
impl IsWatcher<Gui> for Watcher {
fn wait_for_finish(&mut self) -> BoxFuture<Result> {
let Self { web, wasm } = self;
try_join(wasm.wait_ok(), IsWatcher::wait_for_finish(web)).void_ok().boxed()
}
}
/// Override the default value of `newDashboard` in `config.json` to `true`.
///
/// This is a temporary workaround. We want to enable the new dashboard by default in the CI-built
/// IDE, but we don't want to enable it by default in the IDE built locally by developers.
pub fn override_default_for_authentication(
path: &crate::paths::generated::RepoRootAppIdeDesktopLibContentConfigSrcConfigJson,
) -> Result {
let json_path = ["groups", "featurePreview", "options", "newDashboard", "value"];
let mut json = ide_ci::fs::read_json::<serde_json::Value>(path)?;
let mut current =
json.as_object_mut().ok_or_else(|| anyhow!("Failed to find object in {:?}", path))?;
for key in &json_path[..json_path.len() - 1] {
current = current
.get_mut(*key)
.with_context(|| format!("Failed to find {key:?} in {path:?}"))?
.as_object_mut()
.with_context(|| format!("Failed to find object at {key:?} in {path:?}"))?;
}
current.insert(json_path.last().unwrap().to_string(), serde_json::Value::Bool(true));
ide_ci::fs::write_json(path, &json)?;
Ok(())
}
// ==============
// === Target ===
// ==============
/// The [target](IsTarget) for the new GUI.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct Gui;
#[async_trait]
impl IsTarget for Gui {
type BuildInput = BuildInput;
type BuildInput = ();
type Artifact = Artifact;
fn artifact_name(&self) -> String {
"gui".into()
"gui".to_owned()
}
fn adapt_artifact(self, path: impl AsRef<Path>) -> BoxFuture<'static, Result<Self::Artifact>> {
@ -122,107 +169,51 @@ impl IsTarget for Gui {
context: Context,
job: WithDestination<Self::BuildInput>,
) -> BoxFuture<'static, Result<Self::Artifact>> {
let WithDestination { inner, destination } = job;
let WithDestination { inner: _, destination } = job;
async move {
// TODO: [mwu]
// This is a temporary workaround until https://github.com/enso-org/enso/issues/6662
// is resolved.
if ide_ci::actions::workflow::is_in_env() {
let path = &context.repo_root.app.ide_desktop.lib.content_config.src.config_json;
warn!("Overriding default for authentication in {}", path.display());
override_default_for_authentication(path)?;
}
let ide = ide_desktop_from_context(&context);
crate::web::install(&ide.repo_root).await?;
let wasm = Wasm.get(context, inner.wasm);
ide.build_content(wasm, &inner.build_info.await?, &destination).await?;
Ok(Artifact::new(destination.clone()))
let repo_root = &context.repo_root;
crate::ide::web::google_font::install_with_css(
&context.cache,
&context.octocrab,
"mplus1",
"M PLUS 1",
"/font-mplus1",
&repo_root.app.gui_2.public.font_mplus_1,
&repo_root.app.gui_2.src.assets.font_mplus_1_css,
)
.await?;
crate::ide::web::dejavu_font::install_sans_mono_with_css(
&context.cache,
&context.octocrab,
"/font-dejavu",
&repo_root.app.gui_2.public.font_dejavu,
&repo_root.app.gui_2.src.assets.font_dejavu_css,
)
.await?;
crate::ide::web::enso_font::install_with_css(
&context.cache,
&context.octocrab,
"/font-enso",
&repo_root.app.gui_2.public.font_enso,
&repo_root.app.gui_2.src.assets.font_enso_css,
)
.await?;
crate::web::install(repo_root).await?;
script(repo_root, Scripts::Build)?.run_ok().await?;
ide_ci::fs::mirror_directory(
&repo_root.app.gui_2.dist,
&destination.join(RepoRootDistGui2Assets::segment_name()),
)
.await?;
Ok(Artifact::new(destination))
}
.boxed()
}
}
impl IsWatchable for Gui {
type Watcher = Watcher;
type WatchInput = WatchInput;
// fn setup_watcher(
// &self,
// build_input: Self::BuildInput,
// watch_input: Self::WatchInput,
// output_path: impl AsRef<Path> + Send + Sync + 'static,
// ) -> BoxFuture<'static, Result<Self::Watcher>> {
// async move {
// let BuildInput { build_info, repo_root, wasm } = build_input;
// let ide = IdeDesktop::new(&repo_root.app.ide_desktop);
// let watch_process = ide.watch_content(wasm, &build_info.await?).await?;
// let artifact = Self::Artifact::from_existing(output_path).await?;
// Ok(Self::Watcher { watch_process, artifact })
// }
// .boxed()
// }
fn watch(
&self,
context: Context,
job: WatchTargetJob<Self>,
) -> BoxFuture<'static, Result<Self::Watcher>> {
let WatchTargetJob {
watch_input,
build:
WithDestination { inner: BuildSource { input, should_upload_artifact: _ }, destination },
} = job;
let BuildInput { build_info, wasm } = input;
let perhaps_watched_wasm = perhaps_watch(Wasm, context.clone(), wasm, watch_input.wasm);
let ide = ide_desktop_from_context(&context);
async move {
let perhaps_watched_wasm = perhaps_watched_wasm.await?;
let wasm_artifacts = ok_ready_boxed(perhaps_watched_wasm.as_ref().clone());
let watch_process = ide.watch_content(wasm_artifacts, &build_info.await?).await?;
let artifact = Artifact::new(&destination);
let web_watcher = crate::project::Watcher { watch_process, artifact };
Ok(Self::Watcher { wasm: perhaps_watched_wasm, web: web_watcher })
}
.boxed()
}
}
impl Gui {
/// Setup watcher for WASM.
///
/// If the WASM is static (e.g. comes from a release), it will be just referenced.
pub fn perhaps_setup_wasm_watcher(
&self,
context: Context,
job: WatchTargetJob<Self>,
) -> GuiBuildWithWatchedWasm {
let WatchTargetJob {
watch_input,
build:
WithDestination { inner: BuildSource { input, should_upload_artifact: _ }, destination },
} = job;
let BuildInput { build_info, wasm } = input;
let WatchInput { wasm: wasm_watch_input } = watch_input;
let perhaps_watched_wasm = perhaps_watch(Wasm, context, wasm, wasm_watch_input);
GuiBuildWithWatchedWasm { perhaps_watched_wasm, build_info, destination }
}
}
/// Watch job for the `Gui` target with already created watcher for the `Wasm` target.
// Futures cannot be sensibly printed and there is little else of interest here.
#[allow(missing_debug_implementations)]
pub struct GuiBuildWithWatchedWasm {
/// WASM artifacts provider.
pub perhaps_watched_wasm: BoxFuture<'static, Result<PerhapsWatched<Wasm>>>,
/// Information for GUI build.
pub build_info: BoxFuture<'static, Result<BuildInfo>>,
/// Path to the directory where the GUI should be built. Might be ignored in some watching
/// scenarios.
pub destination: PathBuf,
}
// =================
// === BuildInfo ===
// =================
#[derive(Clone, Derivative, Serialize, Deserialize)]
#[derivative(Debug)]
#[serde(rename_all = "camelCase")]

View File

@ -1,211 +0,0 @@
//! Build logic for the "new GUI" (gui2) project.
//!
//! The new GUI is Vue.js-based and located under `app/gui2`.
use crate::prelude::*;
use crate::paths::generated::RepoRootAppGui2Dist;
use crate::paths::generated::RepoRootDistGui2Assets;
use crate::project::Context;
use crate::project::IsArtifact;
use crate::project::IsTarget;
use crate::source::WithDestination;
use ide_ci::ok_ready_boxed;
use ide_ci::programs::node::NpmCommand;
use ide_ci::programs::Npm;
// ===============
// === Scripts ===
// ===============
/// The scripts defined in `package.json`.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, strum::AsRefStr)]
#[strum(serialize_all = "kebab-case")]
pub enum Scripts {
Dev,
Build,
Preview,
Test,
#[strum(serialize = "test:unit")]
TestUnit,
#[strum(serialize = "test:e2e")]
TestE2e,
BuildOnly,
TypeCheck,
Lint,
Format,
BuildRustFfi,
}
pub fn script(repo_root: impl AsRef<Path>, script: Scripts) -> Result<NpmCommand> {
let mut ret = Npm.cmd()?;
ret.current_dir(repo_root).workspace(crate::web::Workspace::EnsoGui2).run(script.as_ref());
Ok(ret)
}
pub fn dashboard_script(repo_root: impl AsRef<Path>, script: Scripts) -> Result<NpmCommand> {
let mut ret = Npm.cmd()?;
ret.current_dir(repo_root).workspace(crate::web::Workspace::EnsoDashboard).run(script.as_ref());
Ok(ret)
}
// ================
// === Commands ===
// ================
/// Run steps that should be done along with the "lint"
pub fn lint(repo_root: impl AsRef<Path>) -> BoxFuture<'static, Result> {
install_and_run_script(Scripts::Lint, repo_root)
}
pub fn tests(repo_root: impl AsRef<Path>) -> BoxFuture<'static, Result> {
install_and_run_script(Scripts::Test, repo_root)
}
pub fn dashboard_tests(repo_root: impl AsRef<Path>) -> BoxFuture<'static, Result> {
install_and_run_dashboard_script(Scripts::Test, repo_root)
}
/// Run unit tests.
pub fn unit_tests(repo_root: impl AsRef<Path>) -> BoxFuture<'static, Result> {
install_and_run_script(Scripts::TestUnit, repo_root)
}
/// Run dashboard unit tests.
pub fn dashboard_unit_tests(repo_root: impl AsRef<Path>) -> BoxFuture<'static, Result> {
install_and_run_dashboard_script(Scripts::TestUnit, repo_root)
}
/// Run E2E tests.
pub fn e2e_tests(repo_root: impl AsRef<Path>) -> BoxFuture<'static, Result> {
install_and_run_script(Scripts::TestE2e, repo_root)
}
/// Run dashboard E2E tests.
pub fn dashboard_e2e_tests(repo_root: impl AsRef<Path>) -> BoxFuture<'static, Result> {
install_and_run_dashboard_script(Scripts::TestE2e, repo_root)
}
pub fn watch(repo_root: impl AsRef<Path>) -> BoxFuture<'static, Result> {
install_and_run_script(Scripts::Dev, repo_root)
}
fn install_and_run_script(
script: Scripts,
repo_root: impl AsRef<Path>,
) -> BoxFuture<'static, Result> {
let repo_root = repo_root.as_ref().to_owned();
async move {
crate::web::install(&repo_root).await?;
self::script(&repo_root, script)?.run_ok().await
}
.boxed()
}
fn install_and_run_dashboard_script(
script: Scripts,
repo_root: impl AsRef<Path>,
) -> BoxFuture<'static, Result> {
let repo_root = repo_root.as_ref().to_owned();
async move {
crate::web::install(&repo_root).await?;
dashboard_script(&repo_root, script)?.run_ok().await
}
.boxed()
}
// ================
// === Artifact ===
// ================
/// The [artifact](IsArtifact) for the new GUI.
#[derive(Clone, Debug, PartialEq, Eq, Hash, Deref)]
pub struct Artifact(pub RepoRootAppGui2Dist);
impl AsRef<Path> for Artifact {
fn as_ref(&self) -> &Path {
self.0.as_path()
}
}
impl IsArtifact for Artifact {}
impl Artifact {
pub fn new(path: impl AsRef<Path>) -> Self {
Artifact(RepoRootAppGui2Dist::new_root(path.as_ref()))
}
}
// ==============
// === Target ===
// ==============
/// The [target](IsTarget) for the new GUI.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct Gui2;
impl IsTarget for Gui2 {
type BuildInput = ();
type Artifact = Artifact;
fn artifact_name(&self) -> String {
"gui2".to_owned()
}
fn adapt_artifact(self, path: impl AsRef<Path>) -> BoxFuture<'static, Result<Self::Artifact>> {
ok_ready_boxed(Artifact::new(path))
}
fn build_internal(
&self,
context: Context,
job: WithDestination<Self::BuildInput>,
) -> BoxFuture<'static, Result<Self::Artifact>> {
let WithDestination { inner: _, destination } = job;
async move {
let repo_root = &context.repo_root;
crate::ide::web::google_font::install_with_css(
&context.cache,
&context.octocrab,
"mplus1",
"M PLUS 1",
"/font-mplus1",
&repo_root.app.gui_2.public.font_mplus_1,
&repo_root.app.gui_2.src.assets.font_mplus_1_css,
)
.await?;
crate::ide::web::dejavu_font::install_sans_mono_with_css(
&context.cache,
&context.octocrab,
"/font-dejavu",
&repo_root.app.gui_2.public.font_dejavu,
&repo_root.app.gui_2.src.assets.font_dejavu_css,
)
.await?;
crate::ide::web::enso_font::install_with_css(
&context.cache,
&context.octocrab,
"/font-enso",
&repo_root.app.gui_2.public.font_enso,
&repo_root.app.gui_2.src.assets.font_enso_css,
)
.await?;
crate::web::install(repo_root).await?;
script(repo_root, Scripts::Build)?.run_ok().await?;
ide_ci::fs::mirror_directory(
&repo_root.app.gui_2.dist,
&destination.join(RepoRootDistGui2Assets::segment_name()),
)
.await?;
Ok(Artifact::new(destination))
}
.boxed()
}
}

View File

@ -1,11 +1,8 @@
#[allow(unused_imports)]
use crate::prelude::*;
use crate::project::gui::ide_desktop_from_context;
use crate::project::gui::GuiBuildWithWatchedWasm;
use crate::project::Context;
use crate::project::Gui;
use crate::project::IsArtifact;
use crate::source::WatchTargetJob;
use ide_ci::actions::artifacts::upload_compressed_directory;
use ide_ci::actions::artifacts::upload_single_file;
@ -102,13 +99,13 @@ impl Artifact {
#[derive(derivative::Derivative)]
#[derivative(Debug)]
pub struct BuildInput<GuiArtifact> {
pub struct BuildInput {
#[derivative(Debug(format_with = "std::fmt::Display::fmt"))]
pub version: Version,
#[derivative(Debug = "ignore")]
pub project_manager: BoxFuture<'static, Result<crate::project::backend::Artifact>>,
#[derivative(Debug = "ignore")]
pub gui: BoxFuture<'static, Result<GuiArtifact>>,
pub gui: BoxFuture<'static, Result<crate::project::gui::Artifact>>,
pub electron_target: Option<String>,
/// The name base used to generate CI run artifact names.
pub artifact_name: String,
@ -130,7 +127,7 @@ impl Ide {
pub fn build(
&self,
context: &Context,
input: BuildInput<impl IsArtifact>,
input: BuildInput,
output_path: impl AsRef<Path> + Send + Sync + 'static,
) -> BoxFuture<'static, Result<Artifact>> {
let BuildInput { version, project_manager, gui, electron_target, artifact_name: _ } = input;
@ -146,25 +143,4 @@ impl Ide {
}
.boxed()
}
/// Setup watch for IDE.
///
/// This includes both WASM watcher and watcher for the web parts.
pub fn watch(
&self,
context: &Context,
gui_watch_job: WatchTargetJob<Gui>,
get_project_manager: BoxFuture<'static, Result<crate::project::backend::Artifact>>,
ide_options: Vec<String>,
) -> BoxFuture<'static, Result> {
let ide_desktop = ide_desktop_from_context(context);
let GuiBuildWithWatchedWasm { perhaps_watched_wasm, build_info, destination: _ } =
Gui.perhaps_setup_wasm_watcher(context.clone(), gui_watch_job);
async move {
ide_desktop
.watch(perhaps_watched_wasm, build_info, get_project_manager, ide_options)
.await
}
.boxed()
}
}

View File

@ -1,9 +0,0 @@
#[allow(unused_imports)]
use crate::prelude::*;
// ==============
// === Export ===
// ==============
pub use crate::project::ide::Artifact;

View File

@ -2,30 +2,8 @@
use crate::prelude::*;
use crate::paths::generated::RepoRootDistWasm;
use crate::project::Context;
use crate::project::IsArtifact;
use crate::project::IsTarget;
use crate::project::IsWatchable;
use crate::source::BuildSource;
use crate::source::WatchTargetJob;
use crate::source::WithDestination;
use derivative::Derivative;
use ide_ci::cache;
use ide_ci::fs::compressed_size;
use ide_ci::fs::copy_file_if_different;
use ide_ci::goodies::shader_tools::ShaderTools;
use ide_ci::programs::cargo;
use ide_ci::programs::wasm_opt;
use ide_ci::programs::wasm_opt::WasmOpt;
use ide_ci::programs::wasm_pack;
use ide_ci::programs::Cargo;
use ide_ci::programs::WasmPack;
use semver::VersionReq;
use std::time::Duration;
use tempfile::tempdir;
use tokio::process::Child;
// ==============
@ -37,19 +15,6 @@ pub mod test;
pub const BINARYEN_VERSION_TO_INSTALL: u32 = 108;
pub const DEFAULT_INTEGRATION_TESTS_WASM_TIMEOUT: Duration = Duration::from_secs(300);
pub const INTEGRATION_TESTS_CRATE_NAME: &str = "enso-integration-test";
pub const OUTPUT_NAME: &str = "ide";
/// Name of the artifact that will be uploaded as part of CI run.
pub const WASM_ARTIFACT_NAME: &str = "gui_wasm";
pub const DEFAULT_TARGET_CRATE: &str = "app/gui";
#[derive(
clap::ArgEnum,
Clone,
@ -91,497 +56,37 @@ pub enum LogLevel {
Trace,
}
#[derive(clap::ArgEnum, Clone, Copy, Debug, PartialEq, Eq, strum::Display, strum::AsRefStr)]
#[strum(serialize_all = "kebab-case")]
pub enum Profile {
Dev,
Profile,
Release,
// Production,
}
impl From<Profile> for wasm_pack::Profile {
fn from(profile: Profile) -> Self {
match profile {
Profile::Dev => Self::Dev,
Profile::Profile => Self::Profile,
Profile::Release => Self::Release,
// Profile::Production => Self::Release,
}
}
}
impl Profile {
pub fn should_check_size(self) -> bool {
match self {
Profile::Dev => false,
Profile::Profile => false,
Profile::Release => true,
// Profile::Production => true,
pub async fn test(repo_root: PathBuf, wasm: &[test::Browser], native: bool) -> Result {
async fn maybe_run<Fut: Future<Output = Result>>(
name: &str,
enabled: bool,
f: impl (FnOnce() -> Fut),
) -> Result {
if enabled {
info!("Will run {name} tests.");
f().await.context(format!("Running {name} tests."))
} else {
info!("Skipping {name} tests.");
Ok(())
}
}
pub fn extra_rust_options(self) -> Vec<String> {
match self {
// Profile::Production => ["-Clto=fat", "-Ccodegen-units=1", "-Cincremental=false"]
// .into_iter()
// .map(ToString::to_string)
// .collect(),
Profile::Dev | Profile::Profile | Profile::Release => vec![],
}
}
pub fn optimization_level(self) -> wasm_opt::OptimizationLevel {
match self {
Profile::Dev => wasm_opt::OptimizationLevel::O0,
Profile::Profile => wasm_opt::OptimizationLevel::O,
Profile::Release => wasm_opt::OptimizationLevel::O3,
}
}
}
#[derive(Clone, Derivative)]
#[derivative(Debug)]
pub struct BuildInput {
/// Path to the crate to be compiled to WAM. Relative to the repository root.
pub crate_path: PathBuf,
pub wasm_opt_options: Vec<String>,
pub skip_wasm_opt: bool,
pub extra_cargo_options: Vec<String>,
pub profile: Profile,
pub profiling_level: Option<ProfilingLevel>,
pub log_level: LogLevel,
pub uncollapsed_log_level: LogLevel,
pub wasm_size_limit: Option<byte_unit::Byte>,
pub system_shader_tools: bool,
}
impl BuildInput {
pub async fn perhaps_check_size(&self, wasm_path: impl AsRef<Path>) -> Result {
let compressed_size = compressed_size(&wasm_path).await?.get_appropriate_unit(true);
info!("Compressed size of {} is {}.", wasm_path.as_ref().display(), compressed_size);
if let Some(wasm_size_limit) = self.wasm_size_limit {
let wasm_size_limit = wasm_size_limit.get_appropriate_unit(true);
if !self.profile.should_check_size() {
warn!("Skipping size check because profile is '{}'.", self.profile,);
} else if self.profiling_level.unwrap_or_default() != ProfilingLevel::Objective {
// TODO? additional leeway as sanity check
warn!(
"Skipping size check because profiling level is {:?} rather than {}.",
self.profiling_level,
ProfilingLevel::Objective
);
} else {
ensure!(
compressed_size < wasm_size_limit,
"Compressed WASM size ~{} ({} bytes) exceeds the limit of {} ({} bytes).",
compressed_size,
compressed_size.get_byte(),
wasm_size_limit,
wasm_size_limit.get_byte(),
)
}
}
Ok(())
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct Wasm;
#[async_trait]
impl IsTarget for Wasm {
type BuildInput = BuildInput;
type Artifact = Artifact;
fn artifact_name(&self) -> String {
WASM_ARTIFACT_NAME.into()
}
fn adapt_artifact(self, path: impl AsRef<Path>) -> BoxFuture<'static, Result<Self::Artifact>> {
ready(Ok(Artifact::new(path.as_ref()))).boxed()
}
fn build_internal(
&self,
context: Context,
job: WithDestination<Self::BuildInput>,
) -> BoxFuture<'static, Result<Self::Artifact>> {
let Context { octocrab: _, cache, repo_root } = context;
let WithDestination { inner, destination } = job;
let span = info_span!("Building WASM.",
repo = %repo_root.display(),
crate = %inner.crate_path.display(),
cargo_opts = ?inner.extra_cargo_options
);
async move {
// Old wasm-pack does not pass trailing `build` command arguments to the Cargo.
// We want to be able to pass --profile this way.
WasmPack.require_present_that(VersionReq::parse(">=0.10.1")?).await?;
let BuildInput {
crate_path,
wasm_opt_options,
skip_wasm_opt,
extra_cargo_options,
profile,
profiling_level,
log_level,
uncollapsed_log_level,
wasm_size_limit: _wasm_size_limit,
system_shader_tools,
} = &inner;
// NOTE: We cannot trust locally installed version of shader tools to be correct.
// Those binaries have no reliable versioning, and existing common distributions (e.g.
// Vulkan SDK) contain old builds with bugs that impact our shaders. By default, we have
// to force usage of our own distribution built on our CI.
if *system_shader_tools {
ShaderTools.install_if_missing(&cache).await?;
} else {
ShaderTools.install(&cache).await?;
}
cache::goodie::binaryen::Binaryen { version: BINARYEN_VERSION_TO_INSTALL }
.install_if_missing(&cache)
.await?;
info!("Building wasm.");
let temp_dir = tempdir()?;
let temp_dist = RepoRootDistWasm::new_root(temp_dir.path());
crate::web::install(&repo_root).await?;
enso_pack::build(
enso_pack::WasmPackOutputs {
out_dir: temp_dist.path.clone(),
out_name: OUTPUT_NAME.into(),
},
|args| {
let mut command = WasmPack.cmd()?;
command
.current_dir(&repo_root)
.kill_on_drop(true)
.env_remove(ide_ci::programs::rustup::env::RUSTUP_TOOLCHAIN.name())
.build()
.arg(wasm_pack::Profile::from(*profile))
.target(wasm_pack::Target::Web)
.output_directory(args.out_dir)
.output_name(args.out_name)
.arg(crate_path)
.arg("--")
.apply(&cargo::Color::Always)
.args(extra_cargo_options);
if let Some(profiling_level) = profiling_level {
command.set_env(env::ENSO_MAX_PROFILING_LEVEL, &profiling_level)?;
}
command.set_env(env::ENSO_MAX_LOG_LEVEL, &log_level)?;
command.set_env(env::ENSO_MAX_UNCOLLAPSED_LOG_LEVEL, &uncollapsed_log_level)?;
Ok(command)
},
)
.await?;
Self::finalize_wasm(wasm_opt_options, *skip_wasm_opt, *profile, &temp_dist).await?;
ide_ci::fs::create_dir_if_missing(&destination)?;
let ret = RepoRootDistWasm::new_root(&destination);
ide_ci::fs::copy(&temp_dist, &ret)?;
inner.perhaps_check_size(&ret.pkg_opt_wasm).await?;
Ok(Artifact(ret))
}
.instrument(span)
.boxed()
}
}
#[derive(Clone, Derivative)]
#[derivative(Debug)]
pub struct WatchInput {
pub cargo_watch_options: Vec<String>,
}
impl IsWatchable for Wasm {
type Watcher = crate::project::Watcher<Self, Child>;
type WatchInput = WatchInput;
fn watch(
&self,
context: Context,
job: WatchTargetJob<Self>,
) -> BoxFuture<'static, Result<Self::Watcher>> {
let span = debug_span!("Watching WASM.", ?job).entered();
// The esbuild watcher must succeed in its first build, or it will prematurely exit.
// See the issue: https://github.com/evanw/esbuild/issues/1063
//
// Because of this, we run first build of wasm manually, rather through cargo-watch.
// After it is completed, the cargo-watch gets spawned and this method yields the watcher.
// This forces esbuild watcher (whose setup requires the watcher artifacts) to wait until
// all wasm build outputs are in place, so the build won't crash.
//
// In general, much neater workaround should be possible, if we stop relying on cargo-watch
// and do the WASM watch directly in the build script.
let first_build_job = self
.build(context.clone(), job.build.clone())
.instrument(debug_span!("Initial single build of WASM before setting up cargo-watch."));
async move {
// Make sure that `npm install` was run, so we can spawned process to skip it.
// This prevents issues with multiple `npm install` invocations running in parallel.
let npm_install = crate::web::install(&context.repo_root);
let (first_build_output, npm_install) =
futures::future::join(first_build_job, npm_install).await;
npm_install?;
let first_build_output = first_build_output?;
let WatchTargetJob {
watch_input: WatchInput { cargo_watch_options: cargo_watch_flags },
build:
WithDestination {
inner: BuildSource { input, should_upload_artifact: _ },
destination,
},
} = job;
let BuildInput {
crate_path,
wasm_opt_options,
skip_wasm_opt,
extra_cargo_options,
profile,
profiling_level,
log_level,
uncollapsed_log_level,
wasm_size_limit,
system_shader_tools: _,
} = input;
let current_exe = std::env::current_exe()?;
// cargo-watch apparently cannot handle verbatim path prefix. We remove it and hope for
// the best.
let current_exe = current_exe.without_verbatim_prefix();
let mut watch_cmd = Cargo.cmd()?;
let (watch_cmd_name, mut watch_cmd_opts) = match std::env::var("USE_CARGO_WATCH_PLUS") {
Ok(_) => ("watch-plus", vec!["--why"]),
Err(_) => ("watch", vec![]),
};
watch_cmd_opts.push("--ignore");
watch_cmd_opts.push("README.md");
watch_cmd
.kill_on_drop(true)
.current_dir(&context.repo_root)
.arg(watch_cmd_name)
.args(watch_cmd_opts)
.args(cargo_watch_flags)
.arg("--");
// === Build Script top-level options ===
watch_cmd
// TODO [mwu]
// This is not nice, as this module should not be aware of the CLI
// parsing/generation. Rather than using `cargo watch` this should
// be implemented directly in Rust.
.arg(current_exe)
.arg("--skip-version-check") // We already checked in the parent process.
.args(["--cache-path", context.cache.path().as_str()])
.args(["--repo-path", context.repo_root.as_str()])
.arg("--skip-npm-install");
// === Build Script command and its options ===
watch_cmd
.arg("wasm")
.arg("build")
.args(["--crate-path", crate_path.as_str()])
.args(["--wasm-output-path", destination.as_str()])
.args(["--wasm-profile", profile.as_ref()]);
if let Some(profiling_level) = profiling_level {
watch_cmd.args(["--profiling-level", profiling_level.to_string().as_str()]);
}
watch_cmd.args(["--wasm-log-level", log_level.to_string().as_str()]);
watch_cmd
.args(["--wasm-uncollapsed-log-level", uncollapsed_log_level.to_string().as_str()]);
for wasm_opt_option in wasm_opt_options {
watch_cmd.args(["--wasm-opt-option", &wasm_opt_option]);
}
if skip_wasm_opt {
watch_cmd.args(["--skip-wasm-opt"]);
}
if let Some(wasm_size_limit) = wasm_size_limit {
watch_cmd.args(["--wasm-size-limit", wasm_size_limit.to_string().as_str()]);
} else {
watch_cmd.args(["--wasm-size-limit", "0"]);
}
// === cargo-watch options ===
watch_cmd.arg("--").args(extra_cargo_options);
let watch_process = watch_cmd.spawn_intercepting()?;
let artifact = Artifact(RepoRootDistWasm::new_root(&destination));
ensure!(
artifact == first_build_output,
"First build output does not match general watch build output. First build output: \
{first_build_output:?}, general watch build output: {artifact:?}",
);
Ok(Self::Watcher { artifact, watch_process })
}
.instrument(span.exit())
.boxed()
}
}
#[derive(Clone, Debug, Display, PartialEq, Eq)]
pub struct Artifact(pub RepoRootDistWasm);
impl Artifact {
pub fn new(path: impl Into<PathBuf>) -> Self {
Self(RepoRootDistWasm::new_root(path))
}
/// Files that should be shipped in the Gui bundle.
pub fn files_to_ship(&self) -> Vec<&Path> {
// We explicitly deconstruct object, so when new fields are added, we will be forced to
// consider whether they should be shipped or not.
let RepoRootDistWasm {
path: _,
dynamic_assets,
pkg_js,
pkg_js_map,
pkg_wasm: _,
pkg_opt_wasm,
} = &self.0;
vec![
dynamic_assets.as_path(),
pkg_js.as_path(),
pkg_js_map.as_path(),
pkg_opt_wasm.as_path(),
]
}
}
impl AsRef<Path> for Artifact {
fn as_ref(&self) -> &Path {
self.0.as_path()
}
}
impl IsArtifact for Artifact {}
impl Wasm {
pub async fn check(&self) -> Result {
maybe_run("native", native, async || {
Cargo
.cmd()?
.apply(&cargo::Command::Check)
.current_dir(repo_root.clone())
.apply(&cargo::Command::Test)
.apply(&cargo::Options::Workspace)
.apply(&cargo::Options::Package(INTEGRATION_TESTS_CRATE_NAME.into()))
.apply(&cargo::Options::AllTargets)
// Color needs to be passed to tests themselves separately.
// See: https://github.com/rust-lang/cargo/issues/1983
.arg("--")
.apply(&cargo::Color::Always)
.run_ok()
.await
}
})
.await?;
pub async fn test(&self, repo_root: PathBuf, wasm: &[test::Browser], native: bool) -> Result {
async fn maybe_run<Fut: Future<Output = Result>>(
name: &str,
enabled: bool,
f: impl (FnOnce() -> Fut),
) -> Result {
if enabled {
info!("Will run {name} tests.");
f().await.context(format!("Running {name} tests."))
} else {
info!("Skipping {name} tests.");
Ok(())
}
}
maybe_run("native", native, async || {
Cargo
.cmd()?
.current_dir(repo_root.clone())
.apply(&cargo::Command::Test)
.apply(&cargo::Options::Workspace)
// Color needs to be passed to tests themselves separately.
// See: https://github.com/rust-lang/cargo/issues/1983
.arg("--")
.apply(&cargo::Color::Always)
.run_ok()
.await
})
.await?;
maybe_run("wasm", !wasm.is_empty(), || test::test_all(repo_root.clone(), wasm)).await?;
Ok(())
}
pub async fn integration_test(
&self,
source_root: PathBuf,
_project_manager: Option<Child>,
headless: bool,
additional_options: Vec<String>,
wasm_timeout: Option<Duration>,
) -> Result {
info!("Running Rust WASM test suite.");
use wasm_pack::TestFlags::*;
WasmPack
.cmd()?
.current_dir(source_root)
.set_env_opt(
env::WASM_BINDGEN_TEST_TIMEOUT,
wasm_timeout.map(|d| d.as_secs()).as_ref(),
)?
.test()
.apply_opt(headless.then_some(&Headless))
.apply(&test::BROWSER_FOR_WASM_TESTS)
.arg("integration-test")
.arg("--profile=integration-test")
.args(additional_options)
.run_ok()
.await
// PM will be automatically killed by dropping the handle.
}
/// Process "raw" WASM (as compiled) by optionally invoking wasm-opt.
pub async fn finalize_wasm(
wasm_opt_options: &[String],
skip_wasm_opt: bool,
profile: Profile,
temp_dist: &RepoRootDistWasm,
) -> Result {
let should_call_wasm_opt = {
if profile == Profile::Dev {
debug!("Skipping wasm-opt invocation, as it is not part of profile {profile}.");
false
} else if skip_wasm_opt {
debug!("Skipping wasm-opt invocation, as it was explicitly requested.");
false
} else {
true
}
};
if should_call_wasm_opt {
let mut wasm_opt_command = WasmOpt.cmd()?;
let has_custom_opt_level = wasm_opt_options.iter().any(|opt| {
wasm_opt::OptimizationLevel::from_str(opt.trim_start_matches('-')).is_ok()
});
if !has_custom_opt_level {
wasm_opt_command.apply(&profile.optimization_level());
}
wasm_opt_command
.args(wasm_opt_options)
.arg(&temp_dist.pkg_wasm)
.apply(&wasm_opt::Output(&temp_dist.pkg_opt_wasm))
.run_ok()
.await?;
} else {
copy_file_if_different(&temp_dist.pkg_wasm, &temp_dist.pkg_opt_wasm)?;
}
Ok(())
}
maybe_run("wasm", !wasm.is_empty(), || test::test_all(repo_root.clone(), wasm)).await?;
Ok(())
}

View File

@ -145,11 +145,11 @@ pub async fn test_all(repo_root: PathBuf, browsers: &[Browser]) -> Result {
for member in all_members {
let member_str = member.to_string_lossy();
if blacklisted(&member) {
info!("Skipping blacklisted crate {member_str}");
debug!("Skipping blacklisted crate: {member_str}");
} else if is_proc_macro_crate(&member) {
info!("Skipping proc-macro crate {member_str}");
debug!("Skipping proc-macro crate: {member_str}");
} else if has_wasm_tests(&member) {
info!("Running tests for {member_str}");
info!("Running tests for: {member_str}");
WasmPack
.cmd()?
.current_dir(&repo_root)
@ -169,7 +169,7 @@ pub async fn test_all(repo_root: PathBuf, browsers: &[Browser]) -> Result {
.run_ok()
.await?;
} else {
println!("No wasm tests in {member_str}");
debug!("Skipping crate with no wasm tests: {member_str}");
}
}
Ok(())

View File

@ -9,11 +9,6 @@ use crate::paths::generated;
use crate::paths::TargetTriple;
use crate::paths::EDITION_FILE_ARTIFACT_NAME;
use crate::project;
use crate::project::gui;
use crate::project::Gui;
use crate::project::IsTarget;
use crate::source::ExternalSource;
use crate::source::FetchTargetJob;
use crate::version;
use crate::version::promote::Designation;
use crate::version::Versions;
@ -242,50 +237,6 @@ pub async fn deploy_to_ecr(context: &BuildContext, repository: String) -> Result
Ok(())
}
/// Download the GUI artifacts from the current CI run artifacts.
pub async fn get_gui_from_current_ci_run(
context: &BuildContext,
out_dir: impl Into<PathBuf>,
) -> Result<gui::Artifact> {
let target = Gui;
let source = ExternalSource::new_ongoing_ci_run(target.artifact_name());
let fetch_job = FetchTargetJob { destination: out_dir.into(), inner: source };
target.get_external(context.inner.clone(), fetch_job).await
}
/// Upload GUI to the cloud (AWS S3).
pub async fn upload_gui_to_cloud_good(context: &BuildContext) -> Result {
let temp = tempdir()?;
let gui = get_gui_from_current_ci_run(context, temp.path()).await?;
upload_gui_to_cloud(&gui.assets, &context.triple.versions.version).await?;
notify_cloud_about_gui(&context.triple.versions.version).await?;
Ok(())
}
/// Upload GUI to the cloud (AWS S3).
pub async fn upload_gui_to_cloud(
assets: &crate::paths::generated::RepoRootDistGuiAssets,
version: &Version,
) -> Result {
let bucket = crate::aws::s3::gui::context(version).await?;
// Some file we upload as-is, some gzipped. This seems somewhat arbitrary now.
let files_to_upload = [
assets.pkg_opt_wasm.as_path(),
assets.style_css.as_path(),
assets.dynamic_assets.as_path(),
];
let files_to_upload_gzipped = [assets.entrypoint_js.as_path(), assets.pkg_js.as_path()];
for file in files_to_upload.iter() {
bucket.put_item(file).await?;
}
put_files_gzipping(&bucket, &files_to_upload_gzipped).await?;
Ok(())
}
/// Packs given files with `gzip` and uploads them to the S3 bucket.
///
/// The files are uploaded with the same name, but with `.gz` extension.
@ -347,19 +298,6 @@ pub async fn promote_release(context: &BuildContext, version_designation: Design
mod tests {
use super::*;
#[tokio::test]
#[ignore]
async fn upload_gui() -> Result {
setup_logging()?;
let assets = crate::paths::generated::RepoRootDistGuiAssets::new_root(
r"H:\NBO\enso4\dist\gui\assets",
);
let version = "2023.1.1-dev.cloud.test".parse2()?;
upload_gui_to_cloud(&assets, &version).await?;
notify_cloud_about_gui(&version).await?;
Ok(())
}
#[tokio::test]
#[ignore]
async fn notify_cloud() -> Result {

View File

@ -20,9 +20,7 @@ pub mod backend;
pub mod engine;
pub mod git_clean;
pub mod gui;
pub mod gui2;
pub mod ide;
pub mod ide2;
pub mod java_gen;
pub mod project_manager;
pub mod release;
@ -114,22 +112,16 @@ macro_rules! source_args_hlp {
pub enum Target {
/// Build/Test the Rust part of the GUI.
Wasm(wasm::Target),
/// Build/Run the legacy Rust-based GUI that consists of WASM and JS parts.
/// Build/Run the Vue-based GUI.
#[clap(alias = "gui2")]
Gui(gui::Target),
/// Build/Run the new, Vue-based GUI.
Gui2(gui2::Target),
/// Enso Engine Runtime.
Runtime(runtime::Target),
// /// Project Manager package (just the binary, no Engine)
// ProjectManager(project_manager::Target),
// /// Enso Engine distribution.
// Engine(engine::Target),
/// Build/Get Project Manager bundle (includes Enso Engine with GraalVM Runtime).
Backend(backend::Target),
/// Build/Run/Test IDE bundle (includes Rust-based GUI and Project Manager).
Ide(ide::Target),
/// Build/Run/Test IDE bundle (includes Vue-based GUI and Project Manager).
Ide2(ide2::Target),
#[clap(alias = "ide2")]
Ide(ide::Target),
/// Clean the repository. Keeps the IntelliJ's .idea directory intact. WARNING: This removes
/// files that are not under version control in the repository subtree.
GitClean(git_clean::Options),

View File

@ -2,34 +2,18 @@ use enso_build::prelude::*;
use crate::arg::BuildJob;
use crate::arg::Source;
use crate::arg::WatchJob;
use crate::source_args_hlp;
use crate::IsWatchableSource;
use clap::Args;
use clap::Subcommand;
use enso_build::project::gui::Gui;
use enso_build::project::wasm::Wasm;
source_args_hlp!(Gui, "gui", BuildInput);
impl IsWatchableSource for Gui {
type WatchInput = WatchInput;
}
#[derive(Args, Clone, Debug, PartialEq)]
pub struct BuildInput {
#[clap(flatten)]
pub wasm: Source<Wasm>,
}
#[derive(Args, Clone, Debug, PartialEq)]
pub struct WatchInput {
#[clap(flatten)]
pub wasm: <Wasm as IsWatchableSource>::WatchInput,
}
#[derive(Args, Clone, Copy, Debug, PartialEq)]
pub struct BuildInput {}
#[derive(Subcommand, Clone, Debug, PartialEq)]
pub enum Command {
@ -37,8 +21,12 @@ pub enum Command {
Build(BuildJob<Gui>),
/// Gets the GUI, either by compiling it from scratch or downloading from an external source.
Get(Source<Gui>),
/// Runs the GUI's unit tests.
Test,
/// Run linter on the GUI's sources.
Lint,
/// Continuously rebuilds GUI when its sources are changed and serves it using dev-server.
Watch(WatchJob<Gui>),
Watch,
}
#[derive(Args, Clone, Debug)]

View File

@ -1,37 +0,0 @@
use enso_build::prelude::*;
use crate::arg::BuildJob;
use crate::arg::Source;
use crate::source_args_hlp;
use clap::Args;
use clap::Subcommand;
use enso_build::project::gui2::Gui2;
source_args_hlp!(Gui2, "gui2", BuildInput);
#[derive(Args, Clone, Copy, Debug, PartialEq)]
pub struct BuildInput {}
#[derive(Subcommand, Clone, Debug, PartialEq)]
pub enum Command {
/// Builds the GUI from the local sources.
Build(BuildJob<Gui2>),
/// Gets the GUI, either by compiling it from scratch or downloading from an external source.
Get(Source<Gui2>),
/// Runs the GUI's unit tests.
Test,
/// Run linter on the GUI's sources.
Lint,
/// Continuously rebuilds GUI when its sources are changed and serves it using dev-server.
Watch,
}
#[derive(Args, Clone, Debug)]
pub struct Target {
/// Command for GUI package.
#[clap(subcommand)]
pub command: Command,
}

View File

@ -1,25 +1,22 @@
use crate::prelude::*;
use crate::arg::IsTargetSource;
use crate::arg::OutputPath;
use crate::arg::Source;
use crate::arg::WatchJob;
use crate::source_args_hlp;
use clap::Args;
use clap::Subcommand;
use enso_build::project::backend::Backend;
use enso_build::project::gui::Gui;
use enso_build::project::wasm::DEFAULT_INTEGRATION_TESTS_WASM_TIMEOUT;
use octocrab::models::ReleaseId;
source_args_hlp!(Target, "ide", BuildInput<Gui, Target>);
source_args_hlp!(Target, "ide", BuildInput);
#[derive(Args, Clone, Debug, Derivative)]
#[derivative(PartialEq)]
pub struct BuildInput<Gui: IsTargetSource, Ide: IsTargetSource = Target> {
pub struct BuildInput {
#[derivative(PartialEq(bound = ""))]
#[clap(flatten)]
pub gui: Source<Gui>,
@ -27,7 +24,7 @@ pub struct BuildInput<Gui: IsTargetSource, Ide: IsTargetSource = Target> {
pub project_manager: Source<Backend>,
#[derivative(PartialEq(bound = ""))]
#[clap(flatten)]
pub output_path: OutputPath<Ide>,
pub output_path: OutputPath<Target>,
/// Override the default target for electron-builder. E.g. pass `dir` for unpacked directory
/// (fastest). See <https://www.electron.build> for all supported targets.
#[clap(long, enso_env())]
@ -40,50 +37,16 @@ pub enum Command {
/// application.
Build {
#[clap(flatten)]
params: BuildInput<Gui>,
params: BuildInput,
},
/// Build and upload the new IDE as a release asset.
/// This command is intended for CI-use only.
Upload {
#[clap(flatten)]
params: BuildInput<Gui>,
params: BuildInput,
#[clap(long, env = *enso_build::env::ENSO_RELEASE_ID)]
release_id: ReleaseId,
},
/// Like `Build` but automatically starts the IDE.
Start {
#[clap(flatten)]
params: BuildInput<Gui>,
/// Additional option to be passed to Enso IDE. Can be used multiple times to pass many
/// arguments.
#[clap(long, allow_hyphen_values = true, enso_env())]
ide_option: Vec<String>,
},
Watch {
#[clap(flatten)]
gui: WatchJob<Gui>,
#[clap(flatten)]
project_manager: Source<Backend>,
#[clap(long, allow_hyphen_values = true, enso_env())]
ide_option: Vec<String>,
},
/// Runs integration tests. This involves building and spawning Project Manager, unless
/// requested otherwise.
IntegrationTest {
/// If set, the project manager won't be spawned.
#[clap(long)]
external_backend: bool,
#[clap(flatten)]
project_manager: Source<Backend>,
/// Run WASM tests in the headless mode
#[clap(long, parse(try_from_str), default_value_t = true)]
headless: bool,
/// Custom timeout for wasm-bindgen test runner. Supports formats like "300secs" or "5min".
#[clap(long, default_value_t = DEFAULT_INTEGRATION_TESTS_WASM_TIMEOUT.into())]
wasm_timeout: humantime::Duration,
/// Additional options to be appended to the wasm-pack invocation. Note that wasm-pack will
/// further redirect any unrecognized option to the underlying cargo call.
#[clap(last = true)]
wasm_pack_options: Vec<String>,
},
}
#[derive(Args, Clone, Debug)]

View File

@ -1,38 +0,0 @@
use crate::prelude::*;
use crate::source_args_hlp;
use clap::Args;
use clap::Subcommand;
use enso_build::project::gui2::Gui2;
use octocrab::models::ReleaseId;
source_args_hlp!(Target, "ide2", BuildInput);
pub type BuildInput = crate::arg::ide::BuildInput<Gui2, Target>;
#[derive(Subcommand, Clone, Debug)]
pub enum Command {
/// Builds both Project Manager and GUI, puts them together into a single, client Electron
/// application.
Build {
#[clap(flatten)]
params: BuildInput,
},
/// Build and upload the new IDE as a release asset.
/// This command is intended for CI-use only.
Upload {
#[clap(flatten)]
params: BuildInput,
#[clap(long, env = *enso_build::env::ENSO_RELEASE_ID)]
release_id: ReleaseId,
},
}
#[derive(Args, Clone, Debug)]
pub struct Target {
#[clap(subcommand)]
pub command: Command,
}

View File

@ -1,111 +1,15 @@
use enso_build::prelude::*;
use crate::arg::ArgExt;
use crate::arg::Source;
use crate::arg::WatchJob;
use crate::source_args_hlp;
use crate::BuildJob;
use crate::IsWatchableSource;
use clap::Args;
use clap::Subcommand;
use enso_build::project::wasm::test::Browser;
use enso_build::project::wasm::Wasm;
use std::sync::OnceLock;
// ==============
// === Export ===
// ==============
pub use enso_build::project::wasm::LogLevel;
pub use enso_build::project::wasm::Profile;
pub use enso_build::project::wasm::ProfilingLevel;
source_args_hlp!(Wasm, "wasm", BuildInput);
impl IsWatchableSource for Wasm {
type WatchInput = WatchInput;
}
static DEFAULT_WASM_SIZE_LIMIT: OnceLock<String> = OnceLock::new();
pub fn initialize_default_wasm_size_limit(limit: byte_unit::Byte) -> Result {
DEFAULT_WASM_SIZE_LIMIT
.set(limit.get_appropriate_unit(true).to_string())
.map_err(|e| anyhow!("WASM size limit was already set to {e}."))
}
#[derive(Args, Clone, Debug, PartialEq, Eq)]
pub struct BuildInput {
/// Which crate should be treated as a WASM entry point. Relative path from source root.
#[clap(default_value = enso_build::project::wasm::DEFAULT_TARGET_CRATE, long, enso_env())]
pub crate_path: PathBuf,
/// Profile that is passed to wasm-pack.
#[clap(long, arg_enum, default_value_t = Profile::Release, enso_env())]
pub wasm_profile: Profile,
/// Additional options to be passed to wasm-opt. Might overwrite the optimization flag
/// resulting from 'wasm_profile' setting.
#[clap(long, allow_hyphen_values = true, enso_env())]
pub wasm_opt_option: Vec<String>,
/// Do not invoke wasm-opt, even if it is part of current profile.
#[clap(long, conflicts_with = "wasm-opt-option", enso_env())]
pub skip_wasm_opt: bool,
/// Additional options to be passed to Cargo.
#[clap(last = true, enso_env())]
pub cargo_options: Vec<String>,
/// Compiles Enso with given profiling level. If not set, defaults to minimum.
#[clap(long, arg_enum, enso_env())]
pub profiling_level: Option<ProfilingLevel>,
/// Compiles Enso with given log level.
#[clap(long, arg_enum, enso_env(), default_value_t)]
pub wasm_log_level: LogLevel,
/// Compiles Enso with given uncollapsed log level.
#[clap(long, arg_enum, enso_env(), default_value_t)]
pub wasm_uncollapsed_log_level: LogLevel,
/// Fail the build if compressed WASM exceeds the specified size. Supports format like
/// "4.06MiB". Pass "0" to disable check.
#[clap(long, enso_env(),
maybe_default = DEFAULT_WASM_SIZE_LIMIT.get(),
default_value_if("skip-wasm-opt", Some("true"), Some("0")),
default_value_if("skip-wasm-opt", None, Some("0")),
)]
pub wasm_size_limit: Option<byte_unit::Byte>,
/// Allow usage of system installation of `shaderc`, `spirv-opt` and `spirv-cross`. When
/// present, the binaries from PATH will be preferred over downloading prebuilt distribution.
/// Caution: old versions of those tools might introduce subtle bugs in optimized shaders.
#[clap(long, enso_env())]
pub system_shader_tools: bool,
}
#[derive(Args, Clone, Debug, PartialEq, Eq)]
pub struct WatchInput {
/// Additional option to be passed to Cargo. Can be used multiple times to pass many arguments.
#[clap(long, allow_hyphen_values = true, enso_env())]
pub cargo_watch_option: Vec<String>,
}
#[derive(Subcommand, Clone, Debug, PartialEq)]
pub enum Command {
/// Build the WASM package.
Build(BuildJob<Wasm>),
/// Lint the codebase.
Check,
/// Get the WASM artifacts from arbitrary source (e.g. release).
Get(Source<Wasm>),
/// Start an ongoing watch process that rebuilds WASM when its sources are touched.
Watch(WatchJob<Wasm>),
/// Run the unit tests.
Test {
/// Skip the native (non-WASM) Rust tests.

View File

@ -38,7 +38,6 @@ use crate::arg::BuildJob;
use crate::arg::Cli;
use crate::arg::IsTargetSource;
use crate::arg::IsWatchableSource;
use crate::arg::OutputPath;
use crate::arg::Target;
use crate::arg::WatchJob;
use anyhow::Context;
@ -56,16 +55,10 @@ use enso_build::project::backend;
use enso_build::project::backend::Backend;
use enso_build::project::gui;
use enso_build::project::gui::Gui;
use enso_build::project::gui2;
use enso_build::project::gui2::Gui2;
use enso_build::project::ide;
use enso_build::project::ide::Ide;
use enso_build::project::ide2;
use enso_build::project::runtime;
use enso_build::project::runtime::Runtime;
use enso_build::project::wasm;
use enso_build::project::wasm::Wasm;
use enso_build::project::IsArtifact;
use enso_build::project::IsTarget;
use enso_build::project::IsWatchable;
use enso_build::project::IsWatcher;
@ -96,7 +89,6 @@ use ide_ci::programs::rustc;
use ide_ci::programs::Cargo;
use octocrab::models::ReleaseId;
use std::time::Duration;
use tempfile::tempdir;
use tokio::process::Child;
pub fn void<T>(_t: T) {}
@ -346,16 +338,12 @@ impl Processor {
pub fn handle_wasm(&self, wasm: arg::wasm::Target) -> BoxFuture<'static, Result> {
match wasm.command {
arg::wasm::Command::Watch(job) => self.watch_and_wait(job),
arg::wasm::Command::Build(job) => self.build(job).void_ok().boxed(),
arg::wasm::Command::Check => Wasm.check().boxed(),
arg::wasm::Command::Test { no_wasm, no_native, browser } => {
let wasm_browsers =
if no_wasm { default() } else { browser.into_iter().map_into().collect_vec() };
let root = self.repo_root.to_path_buf();
async move { Wasm.test(root, &wasm_browsers, !no_native).await }.boxed()
async move { project::wasm::test(root, &wasm_browsers, !no_native).await }.boxed()
}
arg::wasm::Command::Get(source) => self.get(source).void_ok().boxed(),
}
}
@ -363,30 +351,22 @@ impl Processor {
match gui.command {
arg::gui::Command::Build(job) => self.build(job),
arg::gui::Command::Get(source) => self.get(source).void_ok().boxed(),
arg::gui::Command::Watch(job) => self.watch_and_wait(job),
}
}
pub fn handle_gui2(&self, gui: arg::gui2::Target) -> BoxFuture<'static, Result> {
match gui.command {
arg::gui2::Command::Build(job) => self.build(job),
arg::gui2::Command::Get(source) => self.get(source).void_ok().boxed(),
arg::gui2::Command::Test => {
arg::gui::Command::Test => {
let repo_root = self.repo_root.clone();
let gui_tests = run_and_upload_dir(
gui2::tests(&repo_root),
gui::tests(&repo_root),
&repo_root.app.gui_2.playwright_report,
"gui2-playwright-report",
"gui-playwright-report",
);
let dashboard_tests = run_and_upload_dir(
gui2::dashboard_tests(&repo_root),
gui::dashboard_tests(&repo_root),
&repo_root.app.ide_desktop.lib.dashboard.playwright_report,
"dashboard-playwright-report",
);
try_join(gui_tests, dashboard_tests).void_ok().boxed()
}
arg::gui2::Command::Watch => gui2::watch(&self.repo_root),
arg::gui2::Command::Lint => gui2::lint(&self.repo_root),
arg::gui::Command::Watch => gui::watch(&self.repo_root),
arg::gui::Command::Lint => gui::lint(&self.repo_root),
}
}
@ -556,77 +536,11 @@ impl Processor {
pub fn handle_ide(&self, ide: arg::ide::Target) -> BoxFuture<'static, Result> {
match ide.command {
arg::ide::Command::Build { params } => self.build_old_ide(params).void_ok().boxed(),
arg::ide::Command::Build { params } => self.build_ide(params).void_ok().boxed(),
arg::ide::Command::Upload { params, release_id } => {
let build_job = self.build_old_ide(params);
let build_job = self.build_ide(params);
self.upload_ide_assets(build_job, release_id, None)
}
arg::ide::Command::Start { params, ide_option } => {
let build_job = self.build_old_ide(params);
async move {
let ide = build_job.await?;
ide.start_unpacked(ide_option).run_ok().await?;
Ok(())
}
.boxed()
}
arg::ide::Command::Watch { gui, project_manager, ide_option: ide_watch } => {
let context = self.context();
let watch_gui_job = self.resolve_watch_job(gui);
let project_manager = self.get(project_manager);
async move {
crate::project::Ide::default()
.watch(&context, watch_gui_job.await?, project_manager, ide_watch)
.await
}
.boxed()
}
arg::ide::Command::IntegrationTest {
external_backend,
project_manager,
wasm_pack_options,
headless,
wasm_timeout,
} => {
let custom_root = tempdir();
let (custom_root, project_manager) = match custom_root {
Ok(tempdir) => {
let custom_root = Some(tempdir.path().into());
(
Some(tempdir),
Ok(self.spawn_project_manager(project_manager, custom_root)),
)
}
Err(e) => (None, Err(e)),
};
let source_root = self.repo_root.to_path_buf();
async move {
let project_manager =
if !external_backend { Some(project_manager?.await?) } else { None };
Wasm.integration_test(
source_root,
project_manager,
headless,
wasm_pack_options,
Some(wasm_timeout.into()),
)
.await?;
// Custom root must live while the tests are being run.
drop(custom_root);
Ok(())
}
.boxed()
}
}
}
pub fn handle_ide2(&self, ide: arg::ide2::Target) -> BoxFuture<'static, Result> {
match ide.command {
arg::ide2::Command::Build { params } => self.build_new_ide(params).void_ok().boxed(),
arg::ide2::Command::Upload { params, release_id } => {
let build_job = self.build_new_ide(params);
self.upload_ide_assets(build_job, release_id, Some("ide2".into()))
}
}
}
@ -649,43 +563,11 @@ impl Processor {
}
.boxed()
}
pub fn build_ide(
&self,
input: ide::BuildInput<impl IsArtifact>,
output_path: OutputPath<impl IsTargetSource + Send + Sync + 'static>,
params: arg::ide::BuildInput,
) -> BoxFuture<'static, Result<ide::Artifact>> {
let target = Ide { target_os: self.triple.os, target_arch: self.triple.arch };
let artifact_name_prefix = input.artifact_name.clone();
let build_job = target.build(&self.context, input, output_path);
async move {
let artifacts = build_job.await?;
if is_in_env() {
artifacts.upload_as_ci_artifact(artifact_name_prefix).await?;
}
Ok(artifacts)
}
.boxed()
}
pub fn build_old_ide(
&self,
params: arg::ide::BuildInput<Gui>,
) -> BoxFuture<'static, Result<ide::Artifact>> {
let arg::ide::BuildInput { gui, project_manager, output_path, electron_target } = params;
let input = ide::BuildInput {
gui: self.get(gui),
project_manager: self.get(project_manager),
version: self.triple.versions.version.clone(),
electron_target,
artifact_name: "ide".into(),
};
self.build_ide(input, output_path)
}
pub fn build_new_ide(
&self,
params: arg::ide2::BuildInput,
) -> BoxFuture<'static, Result<ide2::Artifact>> {
let arg::ide::BuildInput { gui, project_manager, output_path, electron_target } = params;
let build_info_get = self.js_build_info();
@ -707,9 +589,20 @@ impl Processor {
project_manager: self.get(project_manager),
version: self.triple.versions.version.clone(),
electron_target,
artifact_name: "ide2".into(),
artifact_name: "ide".into(),
};
self.build_ide(input, output_path)
let target = Ide { target_os: self.triple.os, target_arch: self.triple.arch };
let artifact_name_prefix = input.artifact_name.clone();
let build_job = target.build(&self.context, input, output_path);
async move {
let artifacts = build_job.await?;
if is_in_env() {
artifacts.upload_as_ci_artifact(artifact_name_prefix).await?;
}
Ok(artifacts)
}
.boxed()
}
pub fn target<Target: Resolvable>(&self) -> Result<Target> {
@ -726,60 +619,9 @@ pub trait Resolvable: IsTarget + IsTargetSource + Clone {
) -> BoxFuture<'static, Result<<Self as IsTarget>::BuildInput>>;
}
impl Resolvable for Wasm {
fn prepare_target(_context: &Processor) -> Result<Self> {
Ok(Wasm {})
}
fn resolve(
_ctx: &Processor,
from: <Self as IsTargetSource>::BuildInput,
) -> BoxFuture<'static, Result<<Self as IsTarget>::BuildInput>> {
let arg::wasm::BuildInput {
crate_path,
wasm_profile,
wasm_opt_option: wasm_opt_options,
cargo_options,
profiling_level,
wasm_log_level,
wasm_uncollapsed_log_level,
wasm_size_limit,
skip_wasm_opt,
system_shader_tools,
} = from;
ok_ready_boxed(wasm::BuildInput {
crate_path,
wasm_opt_options,
skip_wasm_opt,
extra_cargo_options: cargo_options,
profile: wasm_profile,
profiling_level,
log_level: wasm_log_level,
uncollapsed_log_level: wasm_uncollapsed_log_level,
wasm_size_limit: wasm_size_limit.filter(|size_limit| size_limit.get_bytes() > 0),
system_shader_tools,
})
}
}
impl Resolvable for Gui {
fn prepare_target(_context: &Processor) -> Result<Self> {
Ok(Gui {})
}
fn resolve(
ctx: &Processor,
from: <Self as IsTargetSource>::BuildInput,
) -> BoxFuture<'static, Result<<Self as IsTarget>::BuildInput>> {
let wasm_source = ctx.resolve(Wasm, from.wasm);
let build_info = ctx.js_build_info();
async move { Ok(gui::BuildInput { wasm: wasm_source.await?, build_info }) }.boxed()
}
}
impl Resolvable for Gui2 {
fn prepare_target(_context: &Processor) -> Result<Self> {
Ok(Gui2)
Ok(Gui)
}
fn resolve(
@ -841,24 +683,6 @@ pub trait WatchResolvable: Resolvable + IsWatchableSource + IsWatchable {
) -> Result<<Self as IsWatchable>::WatchInput>;
}
impl WatchResolvable for Wasm {
fn resolve_watch(
_ctx: &Processor,
from: <Self as IsWatchableSource>::WatchInput,
) -> Result<<Self as IsWatchable>::WatchInput> {
Ok(wasm::WatchInput { cargo_watch_options: from.cargo_watch_option })
}
}
impl WatchResolvable for Gui {
fn resolve_watch(
ctx: &Processor,
from: <Self as IsWatchableSource>::WatchInput,
) -> Result<<Self as IsWatchable>::WatchInput> {
Ok(gui::WatchInput { wasm: Wasm::resolve_watch(ctx, from.wasm)? })
}
}
#[tracing::instrument(err, skip(config))]
pub async fn main_internal(config: Option<Config>) -> Result {
trace!("Starting the build process.");
@ -868,11 +692,6 @@ pub async fn main_internal(config: Option<Config>) -> Result {
});
trace!("Creating the build context.");
// Setup that affects Cli parser construction.
if let Some(wasm_size_limit) = config.wasm_size_limit {
crate::arg::wasm::initialize_default_wasm_size_limit(wasm_size_limit)?;
}
debug!("Initial configuration for the CLI driver: {config:#?}");
let cli = Cli::parse();
@ -902,14 +721,9 @@ pub async fn main_internal(config: Option<Config>) -> Result {
match cli.target {
Target::Wasm(wasm) => ctx.handle_wasm(wasm).await?,
Target::Gui(gui) => ctx.handle_gui(gui).await?,
Target::Gui2(gui2) => ctx.handle_gui2(gui2).await?,
Target::Runtime(runtime) => ctx.handle_runtime(runtime).await?,
// Target::ProjectManager(project_manager) =>
// ctx.handle_project_manager(project_manager).await?,
// Target::Engine(engine) => ctx.handle_engine(engine).await?,
Target::Backend(backend) => ctx.handle_backend(backend).await?,
Target::Ide(ide) => ctx.handle_ide(ide).await?,
Target::Ide2(ide2) => ctx.handle_ide2(ide2).await?,
Target::GitClean(options) => {
let crate::arg::git_clean::Options { dry_run, cache, build_script } = options;
let mut exclusions = vec![".idea"];