diff --git a/.github/actions/build-electron/action.yml b/.github/actions/build-electron/action.yml new file mode 100644 index 000000000000..91896502a2cb --- /dev/null +++ b/.github/actions/build-electron/action.yml @@ -0,0 +1,217 @@ +name: 'Build Electron' +description: 'Builds Electron & Friends' +inputs: + target-arch: + description: 'Target arch' + required: true + target-platform: + description: 'Target platform' + required: true + artifact-platform: + description: 'Artifact platform, should be linux, darwin or mas' + required: true + step-suffix: + description: 'Suffix for build steps' + required: false + default: '' + is-release: + description: 'Is release build' + required: true + generate-symbols: + description: 'Generate symbols' + required: true + upload-to-storage: + description: 'Upload to storage' + required: true + is-asan: + description: 'The ASan Linux build' + required: false +runs: + using: "composite" + steps: + - name: Set GN_EXTRA_ARGS for MacOS x64 Builds + shell: bash + if: ${{ inputs.target-arch == 'x64' && inputs.target-platform == 'macos' }} + run: | + GN_APPENDED_ARGS="$GN_EXTRA_ARGS v8_snapshot_toolchain=\"//build/toolchain/mac:clang_x64\"" + echo "GN_EXTRA_ARGS=$GN_APPENDED_ARGS" >> $GITHUB_ENV + - name: Build Electron ${{ inputs.step-suffix }} + shell: bash + run: | + rm -rf "src/out/Default/Electron Framework.framework" + rm -rf src/out/Default/Electron*.app + + cd src/electron + # TODO(codebytere): remove this once we figure out why .git/packed-refs is initially missing + git pack-refs + cd .. + + if [ "`uname`" = "Darwin" ]; then + ulimit -n 10000 + sudo launchctl limit maxfiles 65536 200000 + fi + + NINJA_SUMMARIZE_BUILD=1 e build -j $NUMBER_OF_NINJA_PROCESSES + cp out/Default/.ninja_log out/electron_ninja_log + node electron/script/check-symlinks.js + - name: Strip Electron Binaries ${{ inputs.step-suffix }} + shell: bash + if: ${{ inputs.strip-binaries == 'true' }} + run: | + cd src + electron/script/copy-debug-symbols.py --target-cpu="${{ inputs.target-arch }}" --out-dir=out/Default/debug --compress + electron/script/strip-binaries.py --target-cpu="${{ inputs.target-arch }}" + electron/script/add-debug-link.py --target-cpu="${{ inputs.target-arch }}" --debug-dir=out/Default/debug + - name: Build Electron dist.zip ${{ inputs.step-suffix }} + shell: bash + run: | + cd src + e build electron:electron_dist_zip -j $NUMBER_OF_NINJA_PROCESSES + if [ "${{ inputs.is-asan }}" != "true" ]; then + target_os=${{ inputs.target-platform == 'linux' && 'linux' || 'mac'}} + if [ "${{ inputs.artifact-platform }}" = "mas" ]; then + target_os="${target_os}_mas" + fi + electron/script/zip_manifests/check-zip-manifest.py out/Default/dist.zip electron/script/zip_manifests/dist_zip.$target_os.${{ inputs.target-arch }}.manifest + fi + - name: Build Mksnapshot ${{ inputs.step-suffix }} + shell: bash + run: | + cd src + e build electron:electron_mksnapshot -j $NUMBER_OF_NINJA_PROCESSES + gn desc out/Default v8:run_mksnapshot_default args > out/Default/mksnapshot_args + # Remove unused args from mksnapshot_args + SEDOPTION="-i" + if [ "`uname`" = "Darwin" ]; then + SEDOPTION="-i ''" + fi + sed $SEDOPTION '/.*builtins-pgo/d' out/Default/mksnapshot_args + sed $SEDOPTION '/--turbo-profiling-input/d' out/Default/mksnapshot_args + sed $SEDOPTION '/The gn arg use_goma=true .*/d' out/Default/mksnapshot_args + + if [ "`uname`" = "Linux" ]; then + if [ "${{ inputs.target-arch }}" = "arm" ]; then + electron/script/strip-binaries.py --file $PWD/out/Default/clang_x86_v8_arm/mksnapshot + electron/script/strip-binaries.py --file $PWD/out/Default/clang_x86_v8_arm/v8_context_snapshot_generator + elif [ "${{ inputs.target-arch }}" = "arm64" ]; then + electron/script/strip-binaries.py --file $PWD/out/Default/clang_x64_v8_arm64/mksnapshot + electron/script/strip-binaries.py --file $PWD/out/Default/clang_x64_v8_arm64/v8_context_snapshot_generator + else + electron/script/strip-binaries.py --file $PWD/out/Default/mksnapshot + electron/script/strip-binaries.py --file $PWD/out/Default/v8_context_snapshot_generator + fi + fi + + e build electron:electron_mksnapshot_zip -j $NUMBER_OF_NINJA_PROCESSES + (cd out/Default; zip mksnapshot.zip mksnapshot_args gen/v8/embedded.S) + - name: Generate Cross-Arch Snapshot (arm/arm64) ${{ inputs.step-suffix }} + shell: bash + if: ${{ (inputs.target-arch == 'arm' || inputs.target-arch == 'arm64') && inputs.target-platform == 'linux' }} + run: | + cd src + if [ "${{ inputs.target-arch }}" = "arm" ]; then + MKSNAPSHOT_PATH="clang_x86_v8_arm" + elif [ "${{ inputs.target-arch }}" = "arm64" ]; then + MKSNAPSHOT_PATH="clang_x64_v8_arm64" + fi + + cp "out/Default/$MKSNAPSHOT_PATH/mksnapshot" out/Default + cp "out/Default/$MKSNAPSHOT_PATH/v8_context_snapshot_generator" out/Default + cp "out/Default/$MKSNAPSHOT_PATH/libffmpeg.so" out/Default + + python3 electron/script/verify-mksnapshot.py --source-root "$PWD" --build-dir out/Default --create-snapshot-only + mkdir cross-arch-snapshots + cp out/Default-mksnapshot-test/*.bin cross-arch-snapshots + # Clean up so that ninja does not get confused + rm -f out/Default/libffmpeg.so + - name: Build Chromedriver ${{ inputs.step-suffix }} + shell: bash + run: | + cd src + e build electron:electron_chromedriver -j $NUMBER_OF_NINJA_PROCESSES + e build electron:electron_chromedriver_zip + - name: Build Node.js headers ${{ inputs.step-suffix }} + shell: bash + run: | + cd src + e build electron:node_headers + - name: Generate & Zip Symbols ${{ inputs.step-suffix }} + shell: bash + run: | + # Generate breakpad symbols on release builds + if [ "${{ inputs.generate-symbols }}" = "true" ]; then + e build electron:electron_symbols + fi + cd src + export BUILD_PATH="$(pwd)/out/Default" + e build electron:licenses + e build electron:electron_version_file + if [ "${{ inputs.is-release }}" = "true" ]; then + DELETE_DSYMS_AFTER_ZIP=1 electron/script/zip-symbols.py -b $BUILD_PATH + else + electron/script/zip-symbols.py -b $BUILD_PATH + fi + - name: Generate FFMpeg ${{ inputs.step-suffix }} + shell: bash + if: ${{ inputs.is-release == 'true' }} + run: | + cd src + gn gen out/ffmpeg --args="import(\"//electron/build/args/ffmpeg.gn\") use_remoteexec=true $GN_EXTRA_ARGS" + autoninja -C out/ffmpeg electron:electron_ffmpeg_zip -j $NUMBER_OF_NINJA_PROCESSES + - name: Generate Hunspell Dictionaries ${{ inputs.step-suffix }} + shell: bash + if: ${{ inputs.is-release == 'true' && inputs.target-platform == 'linux' }} + run: | + cd src + autoninja -C out/Default electron:hunspell_dictionaries_zip -j $NUMBER_OF_NINJA_PROCESSES + - name: Generate Libcxx ${{ inputs.step-suffix }} + shell: bash + if: ${{ inputs.is-release == 'true' && inputs.target-platform == 'linux' }} + run: | + cd src + autoninja -C out/Default electron:libcxx_headers_zip -j $NUMBER_OF_NINJA_PROCESSES + autoninja -C out/Default electron:libcxxabi_headers_zip -j $NUMBER_OF_NINJA_PROCESSES + autoninja -C out/Default electron:libcxx_objects_zip -j $NUMBER_OF_NINJA_PROCESSES + - name: Generate TypeScript Definitions ${{ inputs.step-suffix }} + if: ${{ inputs.is-release == 'true' }} + shell: bash + run: | + cd src/electron + node script/yarn create-typescript-definitions + - name: Publish Electron Dist ${{ inputs.step-suffix }} + if: ${{ inputs.is-release == 'true' }} + shell: bash + run: | + rm -rf src/out/Default/obj + cd src/electron + if [ "${{ inputs.upload-to-storage }}" = "1" ]; then + echo 'Uploading Electron release distribution to Azure' + script/release/uploaders/upload.py --verbose --upload_to_storage + else + echo 'Uploading Electron release distribution to GitHub releases' + script/release/uploaders/upload.py --verbose + fi + - name: Generate Artifact Key + shell: bash + run: | + if [ "${{ inputs.is-asan }}" = "true" ]; then + ARTIFACT_KEY=${{ inputs.artifact-platform }}_${{ inputs.target-arch }}_asan + else + ARTIFACT_KEY=${{ inputs.artifact-platform }}_${{ inputs.target-arch }} + fi + echo "ARTIFACT_KEY=$ARTIFACT_KEY" >> $GITHUB_ENV + # The current generated_artifacts_<< artifact.key >> name was taken from CircleCI + # to ensure we don't break anything, but we may be able to improve that. + - name: Move all Generated Artifacts to Upload Folder ${{ inputs.step-suffix }} + shell: bash + run: ./src/electron/script/actions/move-artifacts.sh + - name: Upload Generated Artifacts ${{ inputs.step-suffix }} + uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 + with: + name: generated_artifacts_${{ env.ARTIFACT_KEY }} + path: ./generated_artifacts_${{ inputs.artifact-platform }}_${{ inputs.target-arch }} + - name: Upload Src Artifacts ${{ inputs.step-suffix }} + uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 + with: + name: src_artifacts_${{ env.ARTIFACT_KEY }} + path: ./src_artifacts_${{ inputs.artifact-platform }}_${{ inputs.target-arch }} \ No newline at end of file diff --git a/.github/actions/checkout/action.yml b/.github/actions/checkout/action.yml new file mode 100644 index 000000000000..f57d945fc1f4 --- /dev/null +++ b/.github/actions/checkout/action.yml @@ -0,0 +1,154 @@ +name: 'Checkout' +description: 'Checks out Electron and stores it in the AKS Cache' +inputs: + generate-sas-token: + description: 'Whether to generate and persist a SAS token for the item in the cache' + required: false + default: 'false' +runs: + using: "composite" + steps: + - name: Set GIT_CACHE_PATH to make gclient to use the cache + shell: bash + run: | + echo "GIT_CACHE_PATH=$(pwd)/git-cache" >> $GITHUB_ENV + - name: Install Dependencies + shell: bash + run: | + cd src/electron + node script/yarn install --frozen-lockfile + - name: Get Depot Tools + shell: bash + run: | + git clone --depth=1 https://chromium.googlesource.com/chromium/tools/depot_tools.git + + sed -i '/ninjalog_uploader_wrapper.py/d' ./depot_tools/autoninja + # Remove swift-format dep from cipd on macOS until we send a patch upstream. + cd depot_tools + git apply --3way ../src/electron/.github/workflows/config/gclient.diff + + # Ensure depot_tools does not update. + test -d depot_tools && cd depot_tools + touch .disable_auto_update + - name: Add Depot Tools to PATH + shell: bash + run: echo "$(pwd)/depot_tools" >> $GITHUB_PATH + - name: Generate DEPS Hash + shell: bash + run: | + node src/electron/script/generate-deps-hash.js && cat src/electron/.depshash-target + echo "DEPSHASH=v1-src-cache-$(shasum src/electron/.depshash | cut -f1 -d' ')" >> $GITHUB_ENV + - name: Generate SAS Key + if: ${{ inputs.generate-sas-token == 'true' }} + shell: bash + run: | + curl --unix-socket /var/run/sas/sas.sock --fail "http://foo/$DEPSHASH.tar" > sas-token + - name: Save SAS Key + if: ${{ inputs.generate-sas-token == 'true' }} + uses: actions/cache/save@v4 + with: + path: | + sas-token + key: sas-key-${{ github.run_number }}-${{ github.run_attempt }} + - name: Check If Cache Exists + id: check-cache + shell: bash + run: | + cache_path=/mnt/cross-instance-cache/$DEPSHASH.tar + echo "Using cache key: $DEPSHASH" + echo "Checking for cache in: $cache_path" + if [ ! -f "$cache_path" ]; then + echo "cache_exists=false" >> $GITHUB_OUTPUT + echo "Cache Does Not Exist for $DEPSHASH" + else + echo "cache_exists=false" >> $GITHUB_OUTPUT + echo "Cache Already Exists for $DEPSHASH, Busting cache.." + fi + - name: Gclient Sync + if: steps.check-cache.outputs.cache_exists == 'false' + shell: bash + run: | + gclient config \ + --name "src/electron" \ + --unmanaged \ + ${GCLIENT_EXTRA_ARGS} \ + "$GITHUB_SERVER_URL/$GITHUB_REPOSITORY" + + ELECTRON_USE_THREE_WAY_MERGE_FOR_PATCHES=1 gclient sync --with_branch_heads --with_tags -vvvvv + if [ "${{ inputs.is-release }}" != "true" ]; then + # Re-export all the patches to check if there were changes. + python3 src/electron/script/export_all_patches.py src/electron/patches/config.json + cd src/electron + git update-index --refresh || true + if ! git diff-index --quiet HEAD --; then + # There are changes to the patches. Make a git commit with the updated patches + git add patches + GIT_COMMITTER_NAME="PatchUp" GIT_COMMITTER_EMAIL="73610968+patchup[bot]@users.noreply.github.com" git commit -m "chore: update patches" --author="PatchUp <73610968+patchup[bot]@users.noreply.github.com>" + # Export it + mkdir -p ../../patches + git format-patch -1 --stdout --keep-subject --no-stat --full-index > ../../patches/update-patches.patch + if (node ./script/push-patch.js 2> /dev/null > /dev/null); then + echo + echo "======================================================================" + echo "Changes to the patches when applying, we have auto-pushed the diff to the current branch" + echo "A new CI job will kick off shortly" + echo "======================================================================" + exit 1 + else + echo + echo "======================================================================" + echo "There were changes to the patches when applying." + echo "Check the CI artifacts for a patch you can apply to fix it." + echo "======================================================================" + exit 1 + fi + fi + fi + + # delete all .git directories under src/ except for + # third_party/angle/ and third_party/dawn/ because of build time generation of files + # gen/angle/commit.h depends on third_party/angle/.git/HEAD + # https://chromium-review.googlesource.com/c/angle/angle/+/2074924 + # and dawn/common/Version_autogen.h depends on third_party/dawn/.git/HEAD + # https://dawn-review.googlesource.com/c/dawn/+/83901 + # TODO: maybe better to always leave out */.git/HEAD file for all targets ? + - name: Delete .git directories under src to free space + if: steps.check-cache.outputs.cache_exists == 'false' + shell: bash + run: | + cd src + ( find . -type d -name ".git" -not -path "./third_party/angle/*" -not -path "./third_party/dawn/*" -not -path "./electron/*" ) | xargs rm -rf + - name: Minimize Cache Size for Upload + if: steps.check-cache.outputs.cache_exists == 'false' + shell: bash + run: | + rm -rf src/android_webview + rm -rf src/ios/chrome + rm -rf src/third_party/blink/web_tests + rm -rf src/third_party/blink/perf_tests + rm -rf src/chrome/test/data/xr/webvr_info + rm -rf src/third_party/angle/third_party/VK-GL-CTS/src + rm -rf src/third_party/swift-toolchain + rm -rf src/third_party/swiftshader/tests/regres/testlists + rm -rf src/electron + - name: Compress Src Directory + if: steps.check-cache.outputs.cache_exists == 'false' + shell: bash + run: | + echo "Uncompressed src size: $(du -sh src | cut -f1 -d' ')" + tar -cf $DEPSHASH.tar src + echo "Compressed src to $(du -sh $DEPSHASH.tar | cut -f1 -d' ')" + cp ./$DEPSHASH.tar /mnt/cross-instance-cache/ + - name: Persist Src Cache + if: steps.check-cache.outputs.cache_exists == 'false' + shell: bash + run: | + final_cache_path=/mnt/cross-instance-cache/$DEPSHASH.tar + echo "Using cache key: $DEPSHASH" + echo "Checking path: $final_cache_path" + if [ ! -f "$final_cache_path" ]; then + echo "Cache key not found" + exit 1 + else + echo "Cache key persisted in $final_cache_path" + fi \ No newline at end of file diff --git a/.github/actions/fix-sync-macos/action.yml b/.github/actions/fix-sync-macos/action.yml new file mode 100644 index 000000000000..13f54d90a611 --- /dev/null +++ b/.github/actions/fix-sync-macos/action.yml @@ -0,0 +1,61 @@ +name: 'Fix Sync macOS' +description: 'Checks out Electron and stores it in the AKS Cache' +runs: + using: "composite" + steps: + - name: Fix Sync + shell: bash + # This step is required to correct for differences between "gclient sync" + # on Linux and the expected state on macOS. This requires: + # 1. Fixing Clang Install (wrong binary) + # 2. Fixing esbuild (wrong binary) + # 3. Fixing rustc (wrong binary) + # 4. Fixing gn (wrong binary) + # 5. Fix reclient (wrong binary) + # 6. Fixing dsymutil (wrong binary) + # 7. Ensuring we are using the correct ninja and adding it to PATH + # 8. Fixing angle (wrong remote) + run : | + SEDOPTION="-i ''" + rm -rf src/third_party/llvm-build + python3 src/tools/clang/scripts/update.py + + echo 'infra/3pp/tools/esbuild/${platform}' `gclient getdep --deps-file=src/third_party/devtools-frontend/src/DEPS -r 'third_party/esbuild:infra/3pp/tools/esbuild/${platform}'` > esbuild_ensure_file + # Remove extra output from calling gclient getdep which always calls update_depot_tools + sed -i '' "s/Updating depot_tools... //g" esbuild_ensure_file + cipd ensure --root src/third_party/devtools-frontend/src/third_party/esbuild -ensure-file esbuild_ensure_file + + rm -rf src/third_party/rust-toolchain + python3 src/tools/rust/update_rust.py + + # Prevent calling gclient getdep which always calls update_depot_tools + echo 'gn/gn/mac-${arch}' `gclient getdep --deps-file=src/DEPS -r 'src/buildtools/mac:gn/gn/mac-${arch}'` > gn_ensure_file + sed -i '' "s/Updating depot_tools... //g" gn_ensure_file + cipd ensure --root src/buildtools/mac -ensure-file gn_ensure_file + + # Prevent calling gclient getdep which always calls update_depot_tools + echo 'infra/rbe/client/${platform}' `gclient getdep --deps-file=src/DEPS -r 'src/buildtools/reclient:infra/rbe/client/${platform}'` > gn_ensure_file + sed -i '' "s/Updating depot_tools... //g" gn_ensure_file + cipd ensure --root src/buildtools/reclient -ensure-file gn_ensure_file + python3 src/buildtools/reclient_cfgs/configure_reclient_cfgs.py --rbe_instance "projects/rbe-chrome-untrusted/instances/default_instance" --reproxy_cfg_template reproxy.cfg.template --rewrapper_cfg_project "" --skip_remoteexec_cfg_fetch + + if [ "${{ env.TARGET_ARCH }}" == "arm64" ]; then + DSYM_SHA_FILE=src/tools/clang/dsymutil/bin/dsymutil.arm64.sha1 + else + DSYM_SHA_FILE=src/tools/clang/dsymutil/bin/dsymutil.x64.sha1 + fi + python3 src/third_party/depot_tools/download_from_google_storage.py --no_resume --no_auth --bucket chromium-browser-clang -s $DSYM_SHA_FILE -o src/tools/clang/dsymutil/bin/dsymutil + + echo 'infra/3pp/tools/ninja/${platform}' `gclient getdep --deps-file=src/DEPS -r 'src/third_party/ninja:infra/3pp/tools/ninja/${platform}'` > ninja_ensure_file + sed $SEDOPTION "s/Updating depot_tools... //g" ninja_ensure_file + cipd ensure --root src/third_party/ninja -ensure-file ninja_ensure_file + + echo "$(pwd)/src/third_party/ninja" >> $GITHUB_PATH + + cd src/third_party/angle + rm -f .git/objects/info/alternates + git remote set-url origin https://chromium.googlesource.com/angle/angle.git + cp .git/config .git/config.backup + git remote remove origin + mv .git/config.backup .git/config + git fetch \ No newline at end of file diff --git a/.github/actions/free-space-macos/action.yml b/.github/actions/free-space-macos/action.yml new file mode 100644 index 000000000000..75350ca796ba --- /dev/null +++ b/.github/actions/free-space-macos/action.yml @@ -0,0 +1,65 @@ +name: 'Free Space macOS' +description: 'Checks out Electron and stores it in the AKS Cache' +runs: + using: "composite" + steps: + - name: Free Space on MacOS + shell: bash + run: | + sudo mkdir -p $TMPDIR/del-target + + tmpify() { + if [ -d "$1" ]; then + sudo mv "$1" $TMPDIR/del-target/$(echo $1|shasum -a 256|head -n1|cut -d " " -f1) + fi + } + + strip_universal_deep() { + opwd=$(pwd) + cd $1 + f=$(find . -perm +111 -type f) + for fp in $f + do + if [[ $(file "$fp") == *"universal binary"* ]]; then + if [ "`arch`" == "arm64" ]; then + if [[ $(file "$fp") == *"x86_64"* ]]; then + sudo lipo -remove x86_64 "$fp" -o "$fp" || true + fi + else + if [[ $(file "$fp") == *"arm64e)"* ]]; then + sudo lipo -remove arm64e "$fp" -o "$fp" || true + fi + if [[ $(file "$fp") == *"arm64)"* ]]; then + sudo lipo -remove arm64 "$fp" -o "$fp" || true + fi + fi + fi + done + + cd $opwd + } + + tmpify /Library/Developer/CoreSimulator + tmpify ~/Library/Developer/CoreSimulator + tmpify $(xcode-select -p)/Platforms/AppleTVOS.platform + tmpify $(xcode-select -p)/Platforms/iPhoneOS.platform + tmpify $(xcode-select -p)/Platforms/WatchOS.platform + tmpify $(xcode-select -p)/Platforms/WatchSimulator.platform + tmpify $(xcode-select -p)/Platforms/AppleTVSimulator.platform + tmpify $(xcode-select -p)/Platforms/iPhoneSimulator.platform + tmpify $(xcode-select -p)/Toolchains/XcodeDefault.xctoolchain/usr/metal/ios + tmpify $(xcode-select -p)/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift + tmpify $(xcode-select -p)/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift-5.0 + tmpify ~/.rubies + tmpify ~/Library/Caches/Homebrew + tmpify /usr/local/Homebrew + + sudo rm -rf $TMPDIR/del-target + + sudo rm -rf /Applications/Safari.app + sudo rm -rf ~/project/src/third_party/catapult/tracing/test_data + sudo rm -rf ~/project/src/third_party/angle/third_party/VK-GL-CTS + + # lipo off some huge binaries arm64 versions to save space + strip_universal_deep $(xcode-select -p)/../SharedFrameworks + # strip_arm_deep /System/Volumes/Data/Library/Developer/CommandLineTools/usr \ No newline at end of file diff --git a/.github/actions/install-build-tools/action.yml b/.github/actions/install-build-tools/action.yml new file mode 100644 index 000000000000..cc2050f53252 --- /dev/null +++ b/.github/actions/install-build-tools/action.yml @@ -0,0 +1,11 @@ +name: 'Install Build Tools' +description: 'Installs an exact SHA of build tools' +runs: + using: "composite" + steps: + - name: Install Build Tools + shell: bash + run: | + export BUILD_TOOLS_SHA=ff3e40a9a2ebb735c18b6450ecd5ddaa8bb364a9 + npm i -g @electron/build-tools + e auto-update disable \ No newline at end of file diff --git a/.github/actions/restore-cache-aks/action.yml b/.github/actions/restore-cache-aks/action.yml new file mode 100644 index 000000000000..6dbcd290d805 --- /dev/null +++ b/.github/actions/restore-cache-aks/action.yml @@ -0,0 +1,36 @@ +name: 'Restore Cache AKS' +description: 'Restores Electron src cache via AKS' +runs: + using: "composite" + steps: + - name: Restore and Ensure Src Cache + shell: bash + run: | + cache_path=/mnt/cross-instance-cache/$DEPSHASH.tar + echo "Using cache key: $DEPSHASH" + echo "Checking for cache in: $cache_path" + if [ ! -f "$cache_path" ]; then + echo "Cache Does Not Exist for $DEPSHASH - exiting" + exit 1 + else + echo "Found Cache for $DEPSHASH at $cache_path" + fi + + echo "Persisted cache is $(du -sh $cache_path | cut -f1)" + mkdir temp-cache + tar -xf $cache_path -C temp-cache + echo "Unzipped cache is $(du -sh temp-cache/src | cut -f1)" + + if [ -d "temp-cache/src" ]; then + echo "Relocating Cache" + rm -rf src + mv temp-cache/src src + fi + + if [ ! -d "src/third_party/blink" ]; then + echo "Cache was not correctly restored - exiting" + exit 1 + fi + + echo "Wiping Electron Directory" + rm -rf src/electron \ No newline at end of file diff --git a/.github/actions/restore-cache-azcopy/action.yml b/.github/actions/restore-cache-azcopy/action.yml new file mode 100644 index 000000000000..643585272a1a --- /dev/null +++ b/.github/actions/restore-cache-azcopy/action.yml @@ -0,0 +1,63 @@ +name: 'Restore Cache AZCopy' +description: 'Restores Electron src cache via AZCopy' +runs: + using: "composite" + steps: + - name: Obtain SAS Key + continue-on-error: true + uses: actions/cache/restore@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 + with: + path: | + sas-token + key: sas-key-${{ github.run_number }}-1 + - name: Obtain SAS Key + continue-on-error: true + uses: actions/cache/restore@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 + with: + path: | + sas-token + key: sas-key-${{ github.run_number }}-${{ github.run_attempt }} + - name: Download Src Cache from AKS + # The cache will always exist here as a result of the checkout job + # Either it was uploaded to Azure in the checkout job for this commit + # or it was uploaded in the checkout job for a previous commit. + uses: nick-fields/retry@7152eba30c6575329ac0576536151aca5a72780e # v3.0.0 + with: + timeout_minutes: 20 + max_attempts: 3 + retry_on: error + command: | + sas_token=$(cat sas-token) + if [ -z $sas-token ]; then + echo "SAS Token not found; exiting src cache download early..." + exit 1 + fi + azcopy copy \ + "https://${{ env.AZURE_AKS_CACHE_STORAGE_ACCOUNT }}.file.core.windows.net/${{ env.AZURE_AKS_CACHE_SHARE_NAME }}/${{ env.CACHE_PATH }}?$sas_token" $DEPSHASH.tar + - name: Clean SAS Key + shell: bash + run: rm -f sas-token + - name: Unzip and Ensure Src Cache + shell: bash + run: | + echo "Downloaded cache is $(du -sh $DEPSHASH.tar | cut -f1)" + mkdir temp-cache + tar -xf $DEPSHASH.tar -C temp-cache + echo "Unzipped cache is $(du -sh temp-cache/src | cut -f1)" + + if [ -d "temp-cache/src" ]; then + echo "Relocating Cache" + rm -rf src + mv temp-cache/src src + + echo "Deleting zip file" + rm -rf $DEPSHASH.tar + fi + + if [ ! -d "src/third_party/blink" ]; then + echo "Cache was not correctly restored - exiting" + exit 1 + fi + + echo "Wiping Electron Directory" + rm -rf src/electron \ No newline at end of file diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 000000000000..515ee83c895b --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,245 @@ +name: Build + +on: + workflow_dispatch: + inputs: + build-image-sha: + type: string + description: 'SHA for electron/build image' + default: 'cf814a4d2501e8e843caea071a6b70a48e78b855' + required: true + skip-macos: + type: boolean + description: 'Skip macOS builds' + default: false + required: false + skip-linux: + type: boolean + description: 'Skip Linux builds' + default: false + required: false + skip-lint: + type: boolean + description: 'Skip lint check' + default: false + required: false + push: + branches: + - main + - '[1-9][0-9]-x-y' + pull_request: + +jobs: + setup: + runs-on: ubuntu-latest + permissions: + pull-requests: read + outputs: + docs: ${{ steps.filter.outputs.docs }} + src: ${{ steps.filter.outputs.src }} + build-image-sha: ${{ steps.set-output.outputs.build-image-sha }} + docs-only: ${{ steps.set-output.outputs.docs-only }} + steps: + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 #v4.0.2 + - uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 + id: filter + with: + filters: | + docs: + - 'docs/**' + src: + - '!docs/**' + - name: Set Outputs for Build Image SHA & Docs Only + id: set-output + run: | + if [ -z "${{ inputs.build-image-sha }}" ]; then + echo "build-image-sha=cf814a4d2501e8e843caea071a6b70a48e78b855" >> "$GITHUB_OUTPUT" + else + echo "build-image-sha=${{ inputs.build-image-sha }}" >> "$GITHUB_OUTPUT" + fi + echo "docs-only=${{ steps.filter.outputs.docs == 'true' && steps.filter.outputs.src == 'false' }}" >> "$GITHUB_OUTPUT" + + # Lint Jobs + lint: + needs: setup + if: ${{ !inputs.skip-lint }} + uses: ./.github/workflows/pipeline-electron-lint.yml + with: + container: '{"image":"ghcr.io/electron/build:${{ needs.setup.outputs.build-image-sha }}","options":"--user root"}' + secrets: inherit + + # Docs Only Jobs + docs-only: + needs: setup + if: ${{ needs.setup.outputs.docs-only == 'true' }} + uses: ./.github/workflows/pipeline-electron-docs-only.yml + with: + container: '{"image":"ghcr.io/electron/build:${{ needs.setup.outputs.build-image-sha }}","options":"--user root"}' + secrets: inherit + + # Checkout Jobs + checkout-macos: + needs: setup + if: ${{ needs.setup.outputs.src == 'true' && !inputs.skip-macos}} + runs-on: aks-linux-large + container: + image: ghcr.io/electron/build:${{ needs.setup.outputs.build-image-sha }} + options: --user root + volumes: + - /mnt/cross-instance-cache:/mnt/cross-instance-cache + - /var/run/sas:/var/run/sas + env: + GCLIENT_EXTRA_ARGS: '--custom-var=checkout_mac=True --custom-var=host_os=mac' + outputs: + build-image-sha: ${{ needs.setup.outputs.build-image-sha }} + steps: + - name: Checkout Electron + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 + with: + path: src/electron + fetch-depth: 0 + - name: Checkout & Sync & Save + uses: ./src/electron/.github/actions/checkout + with: + generate-sas-token: 'true' + + checkout-linux: + needs: setup + if: ${{ needs.setup.outputs.src == 'true' && !inputs.skip-linux}} + runs-on: aks-linux-large + container: + image: ghcr.io/electron/build:${{ needs.setup.outputs.build-image-sha }} + options: --user root + volumes: + - /mnt/cross-instance-cache:/mnt/cross-instance-cache + - /var/run/sas:/var/run/sas + env: + GCLIENT_EXTRA_ARGS: '--custom-var=checkout_arm=True --custom-var=checkout_arm64=True' + outputs: + build-image-sha: ${{ needs.setup.outputs.build-image-sha}} + steps: + - name: Checkout Electron + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 + with: + path: src/electron + fetch-depth: 0 + - name: Checkout & Sync & Save + uses: ./src/electron/.github/actions/checkout + + # Build Jobs - These cascade into testing jobs + macos-x64: + permissions: + contents: read + issues: read + pull-requests: read + uses: ./.github/workflows/pipeline-electron-build-and-test.yml + needs: checkout-macos + with: + build-runs-on: macos-14-xlarge + test-runs-on: macos-13 + target-platform: macos + target-arch: x64 + is-release: false + gn-build-type: testing + generate-symbols: false + upload-to-storage: '0' + secrets: inherit + + macos-arm64: + permissions: + contents: read + issues: read + pull-requests: read + uses: ./.github/workflows/pipeline-electron-build-and-test.yml + needs: checkout-macos + with: + build-runs-on: macos-14-xlarge + test-runs-on: macos-14 + target-platform: macos + target-arch: arm64 + is-release: false + gn-build-type: testing + generate-symbols: false + upload-to-storage: '0' + secrets: inherit + + linux-x64: + permissions: + contents: read + issues: read + pull-requests: read + uses: ./.github/workflows/pipeline-electron-build-and-test-and-nan.yml + needs: checkout-linux + with: + build-runs-on: aks-linux-large + test-runs-on: aks-linux-medium + build-container: '{"image":"ghcr.io/electron/build:${{ needs.checkout-linux.outputs.build-image-sha }}","options":"--user root","volumes":["/mnt/cross-instance-cache:/mnt/cross-instance-cache"]}' + test-container: '{"image":"ghcr.io/electron/build:${{ needs.checkout-linux.outputs.build-image-sha }}","options":"--user root --privileged --init"}' + target-platform: linux + target-arch: x64 + is-release: false + gn-build-type: testing + generate-symbols: false + upload-to-storage: '0' + secrets: inherit + + linux-x64-asan: + permissions: + contents: read + issues: read + pull-requests: read + uses: ./.github/workflows/pipeline-electron-build-and-test.yml + needs: checkout-linux + with: + build-runs-on: aks-linux-large + test-runs-on: aks-linux-medium + build-container: '{"image":"ghcr.io/electron/build:${{ needs.checkout-linux.outputs.build-image-sha }}","options":"--user root","volumes":["/mnt/cross-instance-cache:/mnt/cross-instance-cache"]}' + test-container: '{"image":"ghcr.io/electron/build:${{ needs.checkout-linux.outputs.build-image-sha }}","options":"--user root --privileged --init"}' + target-platform: linux + target-arch: x64 + is-release: false + gn-build-type: testing + generate-symbols: false + upload-to-storage: '0' + is-asan: true + secrets: inherit + + linux-arm: + permissions: + contents: read + issues: read + pull-requests: read + uses: ./.github/workflows/pipeline-electron-build-and-test.yml + needs: checkout-linux + with: + build-runs-on: aks-linux-large + test-runs-on: aks-linux-arm-medium + build-container: '{"image":"ghcr.io/electron/build:${{ needs.checkout-linux.outputs.build-image-sha }}","options":"--user root","volumes":["/mnt/cross-instance-cache:/mnt/cross-instance-cache"]}' + test-container: '{"image":"ghcr.io/electron/test:arm32v7-${{ needs.checkout-linux.outputs.build-image-sha }}","options":"--user root --privileged --init","volumes":["/home/runner/externals:/mnt/runner-externals"]}' + target-platform: linux + target-arch: arm + is-release: false + gn-build-type: testing + generate-symbols: false + upload-to-storage: '0' + secrets: inherit + + linux-arm64: + permissions: + contents: read + issues: read + pull-requests: read + uses: ./.github/workflows/pipeline-electron-build-and-test.yml + needs: checkout-linux + with: + build-runs-on: aks-linux-large + test-runs-on: aks-linux-arm-medium + build-container: '{"image":"ghcr.io/electron/build:${{ needs.checkout-linux.outputs.build-image-sha }}","options":"--user root","volumes":["/mnt/cross-instance-cache:/mnt/cross-instance-cache"]}' + test-container: '{"image":"ghcr.io/electron/test:arm64v8-${{ needs.checkout-linux.outputs.build-image-sha }}","options":"--user root --privileged --init"}' + target-platform: linux + target-arch: arm64 + is-release: false + gn-build-type: testing + generate-symbols: false + upload-to-storage: '0' + secrets: inherit \ No newline at end of file diff --git a/.github/workflows/config/gclient.diff b/.github/workflows/config/gclient.diff new file mode 100644 index 000000000000..4a035b8c991f --- /dev/null +++ b/.github/workflows/config/gclient.diff @@ -0,0 +1,14 @@ +diff --git a/gclient.py b/gclient.py +index 59e2b4c5197928bdba1ef69bdbe637d7dfe471c1..b4bae5e48c83c84bd867187afaf40eed16e69851 100755 +--- a/gclient.py ++++ b/gclient.py +@@ -783,7 +783,8 @@ class Dependency(gclient_utils.WorkItem, DependencySettings): + not condition or "non_git_source" not in condition): + continue + cipd_root = self.GetCipdRoot() +- for package in dep_value.get('packages', []): ++ packages = dep_value.get('packages', []) ++ for package in (x for x in packages if "infra/3pp/tools/swift-format" not in x.get('package')): + deps_to_add.append( + CipdDependency(parent=self, + name=name, diff --git a/.github/workflows/linux-publish.yml b/.github/workflows/linux-publish.yml new file mode 100644 index 000000000000..14eedbdd0891 --- /dev/null +++ b/.github/workflows/linux-publish.yml @@ -0,0 +1,83 @@ +name: Publish Linux + +on: + workflow_dispatch: + inputs: + build-image-sha: + type: string + description: 'SHA for electron/build image' + default: 'cf814a4d2501e8e843caea071a6b70a48e78b855' + upload-to-storage: + description: 'Uploads to Azure storage' + required: false + default: '1' + type: string + run-linux-publish: + description: 'Run the publish jobs vs just the build jobs' + type: boolean + default: false + +jobs: + checkout-linux: + runs-on: aks-linux-large + container: + image: ghcr.io/electron/build:${{ inputs.build-image-sha }} + options: --user root + volumes: + - /mnt/cross-instance-cache:/mnt/cross-instance-cache + - /var/run/sas:/var/run/sas + env: + GCLIENT_EXTRA_ARGS: '--custom-var=checkout_arm=True --custom-var=checkout_arm64=True' + steps: + - name: Checkout Electron + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 + with: + path: src/electron + fetch-depth: 0 + - name: Checkout & Sync & Save + uses: ./src/electron/.github/actions/checkout + + publish-x64: + uses: ./.github/workflows/pipeline-segment-electron-build.yml + needs: checkout-linux + with: + environment: production-release + build-runs-on: aks-linux-large + build-container: '{"image":"ghcr.io/electron/build:${{ inputs.build-image-sha }}","options":"--user root","volumes":["/mnt/cross-instance-cache:/mnt/cross-instance-cache"]}' + target-platform: linux + target-arch: x64 + is-release: true + gn-build-type: release + generate-symbols: true + upload-to-storage: ${{ inputs.upload-to-storage }} + secrets: inherit + + publish-arm: + uses: ./.github/workflows/pipeline-segment-electron-build.yml + needs: checkout-linux + with: + environment: production-release + build-runs-on: aks-linux-large + build-container: '{"image":"ghcr.io/electron/build:${{ inputs.build-image-sha }}","options":"--user root","volumes":["/mnt/cross-instance-cache:/mnt/cross-instance-cache"]}' + target-platform: linux + target-arch: arm + is-release: true + gn-build-type: release + generate-symbols: true + upload-to-storage: ${{ inputs.upload-to-storage }} + secrets: inherit + + publish-arm64: + uses: ./.github/workflows/pipeline-segment-electron-build.yml + needs: checkout-linux + with: + environment: production-release + build-runs-on: aks-linux-large + build-container: '{"image":"ghcr.io/electron/build:${{ inputs.build-image-sha }}","options":"--user root","volumes":["/mnt/cross-instance-cache:/mnt/cross-instance-cache"]}' + target-platform: linux + target-arch: arm64 + is-release: true + gn-build-type: release + generate-symbols: true + upload-to-storage: ${{ inputs.upload-to-storage }} + secrets: inherit \ No newline at end of file diff --git a/.github/workflows/macos-publish.yml b/.github/workflows/macos-publish.yml new file mode 100644 index 000000000000..274dd6b4bd8f --- /dev/null +++ b/.github/workflows/macos-publish.yml @@ -0,0 +1,69 @@ +name: Publish MacOS + +on: + workflow_dispatch: + inputs: + build-image-sha: + type: string + description: 'SHA for electron/build image' + default: 'cf814a4d2501e8e843caea071a6b70a48e78b855' + required: true + upload-to-storage: + description: 'Uploads to Azure storage' + required: false + default: '1' + type: string + run-macos-publish: + description: 'Run the publish jobs vs just the build jobs' + type: boolean + default: false + +jobs: + checkout-macos: + runs-on: aks-linux-large + container: + image: ghcr.io/electron/build:${{ inputs.build-image-sha }} + options: --user root + volumes: + - /mnt/cross-instance-cache:/mnt/cross-instance-cache + - /var/run/sas:/var/run/sas + env: + GCLIENT_EXTRA_ARGS: '--custom-var=checkout_mac=True --custom-var=host_os=mac' + steps: + - name: Checkout Electron + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 + with: + path: src/electron + fetch-depth: 0 + - name: Checkout & Sync & Save + uses: ./src/electron/.github/actions/checkout + with: + generate-sas-token: 'true' + + publish-x64: + uses: ./.github/workflows/pipeline-segment-electron-build.yml + needs: checkout-macos + with: + environment: production-release + build-runs-on: macos-14-xlarge + target-platform: macos + target-arch: x64 + is-release: true + gn-build-type: release + generate-symbols: true + upload-to-storage: ${{ inputs.upload-to-storage }} + secrets: inherit + + publish-arm64: + uses: ./.github/workflows/pipeline-segment-electron-build.yml + needs: checkout-macos + with: + environment: production-release + build-runs-on: macos-14-xlarge + target-platform: macos + target-arch: arm64 + is-release: true + gn-build-type: release + generate-symbols: true + upload-to-storage: ${{ inputs.upload-to-storage }} + secrets: inherit \ No newline at end of file diff --git a/.github/workflows/pipeline-electron-build-and-test-and-nan.yml b/.github/workflows/pipeline-electron-build-and-test-and-nan.yml new file mode 100644 index 000000000000..f6ed1fc70648 --- /dev/null +++ b/.github/workflows/pipeline-electron-build-and-test-and-nan.yml @@ -0,0 +1,103 @@ +name: Electron Build & Test (+ Node + NaN) Pipeline + +on: + workflow_call: + inputs: + target-platform: + type: string + description: 'Platform to run on, can be macos or linux' + required: true + target-arch: + type: string + description: 'Arch to build for, can be x64, arm64 or arm' + required: true + build-runs-on: + type: string + description: 'What host to run the build' + required: true + test-runs-on: + type: string + description: 'What host to run the tests on' + required: true + build-container: + type: string + description: 'JSON container information for aks runs-on' + required: false + default: '{"image":null}' + test-container: + type: string + description: 'JSON container information for testing' + required: false + default: '{"image":null}' + is-release: + description: 'Whether this build job is a release job' + required: true + type: boolean + default: false + gn-build-type: + description: 'The gn build type - testing or release' + required: true + type: string + default: testing + generate-symbols: + description: 'Whether or not to generate symbols' + required: true + type: boolean + default: false + upload-to-storage: + description: 'Whether or not to upload build artifacts to external storage' + required: true + type: string + default: '0' + is-asan: + description: 'Building the Address Sanitizer (ASan) Linux build' + required: false + type: boolean + default: false + +concurrency: + group: electron-build-and-test-and-nan-${{ inputs.target-platform }}-${{ inputs.target-arch }}-${{ github.ref }} + cancel-in-progress: ${{ github.ref != 'refs/heads/main' && !endsWith(github.ref, '-x-y') }} + +jobs: + build: + uses: ./.github/workflows/pipeline-segment-electron-build.yml + with: + build-runs-on: ${{ inputs.build-runs-on }} + build-container: ${{ inputs.build-container }} + target-platform: ${{ inputs.target-platform }} + target-arch: ${{ inputs.target-arch }} + is-release: ${{ inputs.is-release }} + gn-build-type: ${{ inputs.gn-build-type }} + generate-symbols: ${{ inputs.generate-symbols }} + upload-to-storage: ${{ inputs.upload-to-storage }} + secrets: inherit + gn-check: + uses: ./.github/workflows/pipeline-segment-electron-gn-check.yml + with: + target-platform: ${{ inputs.target-platform }} + target-arch: ${{ inputs.target-arch }} + check-runs-on: ${{ inputs.build-runs-on }} + check-container: ${{ inputs.build-container }} + gn-build-type: ${{ inputs.gn-build-type }} + is-asan: ${{ inputs.is-asan }} + secrets: inherit + test: + uses: ./.github/workflows/pipeline-segment-electron-test.yml + needs: build + with: + target-arch: ${{ inputs.target-arch }} + target-platform: ${{ inputs.target-platform }} + test-runs-on: ${{ inputs.test-runs-on }} + test-container: ${{ inputs.test-container }} + secrets: inherit + nn-test: + uses: ./.github/workflows/pipeline-segment-node-nan-test.yml + needs: build + with: + target-arch: ${{ inputs.target-arch }} + target-platform: ${{ inputs.target-platform }} + test-runs-on: ${{ inputs.test-runs-on }} + test-container: ${{ inputs.test-container }} + gn-build-type: ${{ inputs.gn-build-type }} + secrets: inherit \ No newline at end of file diff --git a/.github/workflows/pipeline-electron-build-and-test.yml b/.github/workflows/pipeline-electron-build-and-test.yml new file mode 100644 index 000000000000..5501910ddd13 --- /dev/null +++ b/.github/workflows/pipeline-electron-build-and-test.yml @@ -0,0 +1,100 @@ +name: Electron Build & Test Pipeline + +on: + workflow_call: + inputs: + target-platform: + type: string + description: 'Platform to run on, can be macos or linux' + required: true + target-arch: + type: string + description: 'Arch to build for, can be x64, arm64 or arm' + required: true + build-runs-on: + type: string + description: 'What host to run the build' + required: true + test-runs-on: + type: string + description: 'What host to run the tests on' + required: true + build-container: + type: string + description: 'JSON container information for aks runs-on' + required: false + default: '{"image":null}' + test-container: + type: string + description: 'JSON container information for testing' + required: false + default: '{"image":null}' + is-release: + description: 'Whether this build job is a release job' + required: true + type: boolean + default: false + gn-build-type: + description: 'The gn build type - testing or release' + required: true + type: string + default: testing + generate-symbols: + description: 'Whether or not to generate symbols' + required: true + type: boolean + default: false + upload-to-storage: + description: 'Whether or not to upload build artifacts to external storage' + required: true + type: string + default: '0' + is-asan: + description: 'Building the Address Sanitizer (ASan) Linux build' + required: false + type: boolean + default: false + +concurrency: + group: electron-build-and-test-${{ inputs.target-platform }}-${{ inputs.target-arch }}-${{ github.ref }} + cancel-in-progress: ${{ github.ref != 'refs/heads/main' && !endsWith(github.ref, '-x-y') }} + +permissions: + contents: read + issues: read + pull-requests: read + +jobs: + build: + uses: ./.github/workflows/pipeline-segment-electron-build.yml + with: + build-runs-on: ${{ inputs.build-runs-on }} + build-container: ${{ inputs.build-container }} + target-platform: ${{ inputs.target-platform }} + target-arch: ${{ inputs.target-arch }} + is-release: ${{ inputs.is-release }} + gn-build-type: ${{ inputs.gn-build-type }} + generate-symbols: ${{ inputs.generate-symbols }} + upload-to-storage: ${{ inputs.upload-to-storage }} + is-asan: ${{ inputs.is-asan}} + secrets: inherit + gn-check: + uses: ./.github/workflows/pipeline-segment-electron-gn-check.yml + with: + target-platform: ${{ inputs.target-platform }} + target-arch: ${{ inputs.target-arch }} + check-runs-on: ${{ inputs.build-runs-on }} + check-container: ${{ inputs.build-container }} + gn-build-type: ${{ inputs.gn-build-type }} + is-asan: ${{ inputs.is-asan }} + secrets: inherit + test: + uses: ./.github/workflows/pipeline-segment-electron-test.yml + needs: build + with: + target-arch: ${{ inputs.target-arch }} + target-platform: ${{ inputs.target-platform }} + test-runs-on: ${{ inputs.test-runs-on }} + test-container: ${{ inputs.test-container }} + is-asan: ${{ inputs.is-asan}} + secrets: inherit \ No newline at end of file diff --git a/.github/workflows/pipeline-electron-docs-only.yml b/.github/workflows/pipeline-electron-docs-only.yml new file mode 100644 index 000000000000..a4971b9babaa --- /dev/null +++ b/.github/workflows/pipeline-electron-docs-only.yml @@ -0,0 +1,43 @@ +name: Electron Docs Compile + +on: + workflow_call: + inputs: + container: + required: true + description: 'Container to run the docs-only ts compile in' + type: string + +concurrency: + group: electron-docs-only-${{ github.ref }} + cancel-in-progress: true + +jobs: + docs-only: + name: Docs Only Compile + runs-on: aks-linux-medium + timeout-minutes: 20 + container: ${{ fromJSON(inputs.container) }} + steps: + - name: Checkout Electron + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 + with: + path: src/electron + fetch-depth: 0 + - name: Install Dependencies + run: | + cd src/electron + node script/yarn install --frozen-lockfile + - name: Run TS/JS compile + shell: bash + run: | + cd src/electron + node script/yarn create-typescript-definitions + node script/yarn tsc -p tsconfig.default_app.json --noEmit + for f in build/webpack/*.js + do + out="${f:29}" + if [ "$out" != "base.js" ]; then + node script/yarn webpack --config $f --output-filename=$out --output-path=./.tmp --env mode=development + fi + done \ No newline at end of file diff --git a/.github/workflows/pipeline-electron-lint.yml b/.github/workflows/pipeline-electron-lint.yml new file mode 100644 index 000000000000..c104a2aa9c75 --- /dev/null +++ b/.github/workflows/pipeline-electron-lint.yml @@ -0,0 +1,77 @@ +name: Electron Lint + +on: + workflow_call: + inputs: + container: + required: true + description: 'Container to run lint in' + type: string + +concurrency: + group: electron-lint-${{ github.ref }} + cancel-in-progress: ${{ github.ref != 'refs/heads/main' && !endsWith(github.ref, '-x-y') }} + +jobs: + lint: + name: Lint + runs-on: aks-linux-medium + timeout-minutes: 20 + container: ${{ fromJSON(inputs.container) }} + steps: + - name: Checkout Electron + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 + with: + path: src/electron + fetch-depth: 0 + - name: Install Dependencies + run: | + cd src/electron + node script/yarn install --frozen-lockfile + - name: Setup third_party Depot Tools + shell: bash + run: | + # "depot_tools" has to be checkout into "//third_party/depot_tools" so pylint.py can a "pylintrc" file. + git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git src/third_party/depot_tools + echo "$(pwd)/src/third_party/depot_tools" >> $GITHUB_PATH + - name: Download GN Binary + shell: bash + run: | + chromium_revision="$(grep -A1 chromium_version src/electron/DEPS | tr -d '\n' | cut -d\' -f4)" + gn_version="$(curl -sL "https://chromium.googlesource.com/chromium/src/+/${chromium_revision}/DEPS?format=TEXT" | base64 -d | grep gn_version | head -n1 | cut -d\' -f4)" + + cipd ensure -ensure-file - -root . <<-CIPD + \$ServiceURL https://chrome-infra-packages.appspot.com/ + @Subdir src/buildtools/linux64 + gn/gn/linux-amd64 $gn_version + CIPD + + buildtools_path="$(pwd)/src/buildtools" + echo "CHROMIUM_BUILDTOOLS_PATH=$buildtools_path" >> $GITHUB_ENV + - name: Download clang-format Binary + shell: bash + run: | + chromium_revision="$(grep -A1 chromium_version src/electron/DEPS | tr -d '\n' | cut -d\' -f4)" + + sha1_path='buildtools/linux64/clang-format.sha1' + curl -sL "https://chromium.googlesource.com/chromium/src/+/${chromium_revision}/${sha1_path}?format=TEXT" | base64 -d > "src/${sha1_path}" + + download_from_google_storage.py --no_resume --no_auth --bucket chromium-clang-format -s "src/${sha1_path}" + - name: Run Lint + shell: bash + run: | + # gn.py tries to find a gclient root folder starting from the current dir. + # When it fails and returns "None" path, the whole script fails. Let's "fix" it. + touch .gclient + # Another option would be to checkout "buildtools" inside the Electron checkout, + # but then we would lint its contents (at least gn format), and it doesn't pass it. + + cd src/electron + node script/yarn install --frozen-lockfile + node script/yarn lint + - name: Run Script Typechecker + shell: bash + run: | + cd src/electron + node script/yarn tsc -p tsconfig.script.json + \ No newline at end of file diff --git a/.github/workflows/pipeline-segment-electron-build.yml b/.github/workflows/pipeline-segment-electron-build.yml new file mode 100644 index 000000000000..839ed923f172 --- /dev/null +++ b/.github/workflows/pipeline-segment-electron-build.yml @@ -0,0 +1,207 @@ +name: Pipeline Segment - Electron Build + +on: + workflow_call: + inputs: + environment: + description: using the production or testing environment + required: false + type: string + target-platform: + type: string + description: 'Platform to run on, can be macos or linux' + required: true + target-arch: + type: string + description: 'Arch to build for, can be x64, arm64 or arm' + required: true + build-runs-on: + type: string + description: 'What host to run the build' + required: true + build-container: + type: string + description: 'JSON container information for aks runs-on' + required: false + default: '{"image":null}' + is-release: + description: 'Whether this build job is a release job' + required: true + type: boolean + default: false + gn-build-type: + description: 'The gn build type - testing or release' + required: true + type: string + default: testing + generate-symbols: + description: 'Whether or not to generate symbols' + required: true + type: boolean + default: false + upload-to-storage: + description: 'Whether or not to upload build artifacts to external storage' + required: true + type: string + default: '0' + is-asan: + description: 'Building the Address Sanitizer (ASan) Linux build' + required: false + type: boolean + default: false + + +concurrency: + group: electron-build-${{ inputs.target-platform }}-${{ inputs.target-arch }}-${{ inputs.is-asan }}-${{ github.ref }} + cancel-in-progress: ${{ github.ref != 'refs/heads/main' && !endsWith(github.ref, '-x-y') }} + +env: + AZURE_AKS_CACHE_STORAGE_ACCOUNT: ${{ secrets.AZURE_AKS_CACHE_STORAGE_ACCOUNT }} + AZURE_AKS_CACHE_SHARE_NAME: ${{ secrets.AZURE_AKS_CACHE_SHARE_NAME }} + ELECTRON_ARTIFACTS_BLOB_STORAGE: ${{ secrets.ELECTRON_ARTIFACTS_BLOB_STORAGE }} + ELECTRON_RBE_JWT: ${{ secrets.ELECTRON_RBE_JWT }} + ELECTRON_GITHUB_TOKEN: ${{ secrets.ELECTRON_GITHUB_TOKEN }} + GCLIENT_EXTRA_ARGS: ${{ inputs.target-platform == 'macos' && '--custom-var=checkout_mac=True --custom-var=host_os=mac' || '--custom-var=checkout_arm=True --custom-var=checkout_arm64=True' }} + ELECTRON_OUT_DIR: Default + +jobs: + build: + runs-on: ${{ inputs.build-runs-on }} + container: ${{ fromJSON(inputs.build-container) }} + environment: ${{ inputs.environment }} + env: + TARGET_ARCH: ${{ inputs.target-arch }} + steps: + - name: Create src dir + run: mkdir src + - name: Checkout Electron + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 + with: + path: src/electron + fetch-depth: 0 + - name: Setup Node.js/npm + if: ${{ inputs.target-platform == 'macos' }} + uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 + with: + node-version: 20.11.x + cache: yarn + cache-dependency-path: src/electron/yarn.lock + - name: Install Dependencies + run: | + cd src/electron + node script/yarn install --frozen-lockfile + - name: Install AZCopy + if: ${{ inputs.target-platform == 'macos' }} + run: brew install azcopy + - name: Set GN_EXTRA_ARGS for Linux + if: ${{ inputs.target-platform == 'linux' }} + run: | + if [ "${{ inputs.target-arch }}" = "arm" ]; then + if [ "${{ inputs.is-release }}" = true ]; then + GN_EXTRA_ARGS='target_cpu="arm" build_tflite_with_xnnpack=false symbol_level=1' + else + GN_EXTRA_ARGS='target_cpu="arm" build_tflite_with_xnnpack=false' + fi + elif [ "${{ inputs.target-arch }}" = "arm64" ]; then + GN_EXTRA_ARGS='target_cpu="arm64" fatal_linker_warnings=false enable_linux_installer=false' + elif [ "${{ inputs.is-asan }}" = true ]; then + GN_EXTRA_ARGS='is_asan=true' + fi + echo "GN_EXTRA_ARGS=$GN_EXTRA_ARGS" >> $GITHUB_ENV + - name: Get Depot Tools + timeout-minutes: 5 + run: | + git clone --depth=1 https://chromium.googlesource.com/chromium/tools/depot_tools.git + + SEDOPTION="-i" + if [ "`uname`" = "Darwin" ]; then + SEDOPTION="-i ''" + fi + + # remove ninjalog_uploader_wrapper.py from autoninja since we don't use it and it causes problems + sed $SEDOPTION '/ninjalog_uploader_wrapper.py/d' ./depot_tools/autoninja + + # Ensure depot_tools does not update. + test -d depot_tools && cd depot_tools + if [ "`uname`" = "Linux" ]; then + git apply --3way ../src/electron/.github/workflows/config/gclient.diff + fi + touch .disable_auto_update + - name: Add Depot Tools to PATH + run: echo "$(pwd)/depot_tools" >> $GITHUB_PATH + - name: Generate DEPS Hash + run: | + node src/electron/script/generate-deps-hash.js && cat src/electron/.depshash-target + DEPSHASH=v1-src-cache-$(shasum src/electron/.depshash | cut -f1 -d' ') + echo "DEPSHASH=$DEPSHASH" >> $GITHUB_ENV + echo "CACHE_PATH=$DEPSHASH.tar" >> $GITHUB_ENV + - name: Restore src cache via AZCopy + if: ${{ inputs.target-platform == 'macos' }} + uses: ./src/electron/.github/actions/restore-cache-azcopy + - name: Restore src cache via AKS + if: ${{ inputs.target-platform == 'linux' }} + uses: ./src/electron/.github/actions/restore-cache-aks + - name: Checkout Electron + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 + with: + path: src/electron + fetch-depth: 0 + - name: Install Build Tools + uses: ./src/electron/.github/actions/install-build-tools + - name: Init Build Tools + run: | + e init -f --root=$(pwd) --out=Default ${{ inputs.gn-build-type }} --import ${{ inputs.gn-build-type }} --target-cpu ${{ inputs.target-arch }} --only-sdk + - name: Run Electron Only Hooks + run: | + gclient runhooks --spec="solutions=[{'name':'src/electron','url':None,'deps_file':'DEPS','custom_vars':{'process_deps':False},'managed':False}]" + - name: Regenerate DEPS Hash + run: | + (cd src/electron && git checkout .) && node src/electron/script/generate-deps-hash.js && cat src/electron/.depshash-target + echo "DEPSHASH=$(shasum src/electron/.depshash | cut -f1 -d' ')" >> $GITHUB_ENV + - name: Add CHROMIUM_BUILDTOOLS_PATH to env + run: echo "CHROMIUM_BUILDTOOLS_PATH=$(pwd)/src/buildtools" >> $GITHUB_ENV + - name: Fix Sync (macOS) + if: ${{ inputs.target-platform == 'macos' }} + uses: ./src/electron/.github/actions/fix-sync-macos + - name: Install build-tools & Setup RBE + run: | + echo "NUMBER_OF_NINJA_PROCESSES=${{ inputs.target-platform == 'linux' && '300' || '200' }}" >> $GITHUB_ENV + cd ~/.electron_build_tools + npx yarn --ignore-engines + # Pull down credential helper and print status + node -e "require('./src/utils/reclient.js').downloadAndPrepare({})" + HELPER=$(node -p "require('./src/utils/reclient.js').helperPath({})") + $HELPER login + echo 'RBE_service='`node -e "console.log(require('./src/utils/reclient.js').serviceAddress)"` >> $GITHUB_ENV + echo 'RBE_experimental_credentials_helper='`node -e "console.log(require('./src/utils/reclient.js').helperPath({}))"` >> $GITHUB_ENV + echo 'RBE_experimental_credentials_helper_args=print' >> $GITHUB_ENV + - name: Free up space (macOS) + if: ${{ inputs.target-platform == 'macos' }} + uses: ./src/electron/.github/actions/free-space-macos + - name: Build Electron + uses: ./src/electron/.github/actions/build-electron + with: + target-arch: ${{ inputs.target-arch }} + target-platform: ${{ inputs.target-platform }} + artifact-platform: ${{ inputs.target-platform == 'linux' && 'linux' || 'darwin' }} + is-release: '${{ inputs.is-release }}' + generate-symbols: '${{ inputs.generate-symbols }}' + upload-to-storage: '${{ inputs.upload-to-storage }}' + is-asan: '${{ inputs.is-asan }}' + - name: Set GN_EXTRA_ARGS for MAS Build + if: ${{ inputs.target-platform == 'macos' }} + run: | + echo "MAS_BUILD=true" >> $GITHUB_ENV + GN_EXTRA_ARGS='is_mas_build=true' + echo "GN_EXTRA_ARGS=$GN_EXTRA_ARGS" >> $GITHUB_ENV + - name: Build Electron (MAS) + if: ${{ inputs.target-platform == 'macos' }} + uses: ./src/electron/.github/actions/build-electron + with: + target-arch: ${{ inputs.target-arch }} + target-platform: ${{ inputs.target-platform }} + artifact-platform: 'mas' + is-release: '${{ inputs.is-release }}' + generate-symbols: '${{ inputs.generate-symbols }}' + upload-to-storage: '${{ inputs.upload-to-storage }}' + step-suffix: '(mas)' \ No newline at end of file diff --git a/.github/workflows/pipeline-segment-electron-gn-check.yml b/.github/workflows/pipeline-segment-electron-gn-check.yml new file mode 100644 index 000000000000..101a9656670f --- /dev/null +++ b/.github/workflows/pipeline-segment-electron-gn-check.yml @@ -0,0 +1,143 @@ +name: Pipeline Segment - Electron GN Check + +on: + workflow_call: + inputs: + target-platform: + type: string + description: 'Platform to run on, can be macos or linux' + required: true + target-arch: + type: string + description: 'Arch to build for, can be x64, arm64 or arm' + required: true + check-runs-on: + type: string + description: 'What host to run the tests on' + required: true + check-container: + type: string + description: 'JSON container information for aks runs-on' + required: false + default: '{"image":null}' + gn-build-type: + description: 'The gn build type - testing or release' + required: true + type: string + default: testing + is-asan: + description: 'Building the Address Sanitizer (ASan) Linux build' + required: false + type: boolean + default: false + +concurrency: + group: electron-gn-check-${{ inputs.target-platform }}-${{ inputs.target-arch }}-${{ inputs.is-asan }}-${{ github.ref }} + cancel-in-progress: true + +env: + AZURE_AKS_CACHE_STORAGE_ACCOUNT: ${{ secrets.AZURE_AKS_CACHE_STORAGE_ACCOUNT }} + AZURE_AKS_CACHE_SHARE_NAME: ${{ secrets.AZURE_AKS_CACHE_SHARE_NAME }} + ELECTRON_RBE_JWT: ${{ secrets.ELECTRON_RBE_JWT }} + GCLIENT_EXTRA_ARGS: ${{ inputs.target-platform == 'macos' && '--custom-var=checkout_mac=True --custom-var=host_os=mac' || '--custom-var=checkout_arm=True --custom-var=checkout_arm64=True' }} + ELECTRON_OUT_DIR: Default + TARGET_ARCH: ${{ inputs.target-arch }} + +jobs: + gn-check: + # TODO(codebytere): Change this to medium VM + runs-on: ${{ inputs.check-runs-on }} + container: ${{ fromJSON(inputs.check-container) }} + env: + TARGET_ARCH: ${{ inputs.target-arch }} + steps: + - name: Checkout Electron + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 + with: + path: src/electron + fetch-depth: 0 + - name: Install Build Tools + uses: ./src/electron/.github/actions/install-build-tools + - name: Init Build Tools + run: | + e init -f --root=$(pwd) --out=Default ${{ inputs.gn-build-type }} --import ${{ inputs.gn-build-type }} --target-cpu ${{ inputs.target-arch }} --only-sdk + - name: Get Depot Tools + timeout-minutes: 5 + run: | + git clone --depth=1 https://chromium.googlesource.com/chromium/tools/depot_tools.git + + SEDOPTION="-i" + if [ "`uname`" = "Darwin" ]; then + SEDOPTION="-i ''" + fi + + # remove ninjalog_uploader_wrapper.py from autoninja since we don't use it and it causes problems + sed $SEDOPTION '/ninjalog_uploader_wrapper.py/d' ./depot_tools/autoninja + + # Ensure depot_tools does not update. + test -d depot_tools && cd depot_tools + if [ "`uname`" = "Linux" ]; then + git apply --3way ../src/electron/.github/workflows/config/gclient.diff + fi + touch .disable_auto_update + - name: Add Depot Tools to PATH + run: echo "$(pwd)/depot_tools" >> $GITHUB_PATH + - name: Set GN_EXTRA_ARGS for Linux + if: ${{ inputs.target-platform == 'linux' }} + run: | + if [ "${{ inputs.target-arch }}" = "arm" ]; then + GN_EXTRA_ARGS='build_tflite_with_xnnpack=false' + elif [ "${{ inputs.target-arch }}" = "arm64" ]; then + GN_EXTRA_ARGS='fatal_linker_warnings=false enable_linux_installer=false' + fi + echo "GN_EXTRA_ARGS=$GN_EXTRA_ARGS" >> $GITHUB_ENV + - name: Generate DEPS Hash + run: | + node src/electron/script/generate-deps-hash.js && cat src/electron/.depshash-target + DEPSHASH=v1-src-cache-$(shasum src/electron/.depshash | cut -f1 -d' ') + echo "DEPSHASH=$DEPSHASH" >> $GITHUB_ENV + echo "CACHE_PATH=$DEPSHASH.tar" >> $GITHUB_ENV + - name: Restore src cache via AZCopy + if: ${{ inputs.target-platform == 'macos' }} + uses: ./src/electron/.github/actions/restore-cache-azcopy + - name: Restore src cache via AKS + if: ${{ inputs.target-platform == 'linux' }} + uses: ./src/electron/.github/actions/restore-cache-aks + - name: Run Electron Only Hooks + run: | + gclient runhooks --spec="solutions=[{'name':'src/electron','url':None,'deps_file':'DEPS','custom_vars':{'process_deps':False},'managed':False}]" + - name: Regenerate DEPS Hash + run: | + (cd src/electron && git checkout .) && node src/electron/script/generate-deps-hash.js && cat src/electron/.depshash-target + echo "DEPSHASH=$(shasum src/electron/.depshash | cut -f1 -d' ')" >> $GITHUB_ENV + - name: Add CHROMIUM_BUILDTOOLS_PATH to env + run: echo "CHROMIUM_BUILDTOOLS_PATH=$(pwd)/src/buildtools" >> $GITHUB_ENV + - name: Checkout Electron + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 + with: + path: src/electron + fetch-depth: 0 + - name: Default GN gen + run: | + cd src/electron + git pack-refs + cd .. + + e build --only-gen + - name: Run GN Check + run: | + cd src + gn check out/Default //electron:electron_lib + gn check out/Default //electron:electron_app + gn check out/Default //electron/shell/common/api:mojo + + # Check the hunspell filenames + node electron/script/gen-hunspell-filenames.js --check + node electron/script/gen-libc++-filenames.js --check + - name: Wait for active SSH sessions + if: always() && !cancelled() + run: | + while [ -f /var/.ssh-lock ] + do + sleep 60 + done \ No newline at end of file diff --git a/.github/workflows/pipeline-segment-electron-test.yml b/.github/workflows/pipeline-segment-electron-test.yml new file mode 100644 index 000000000000..fb9e6780235c --- /dev/null +++ b/.github/workflows/pipeline-segment-electron-test.yml @@ -0,0 +1,196 @@ +name: Pipeline Segment - Electron Test + +on: + workflow_call: + inputs: + target-platform: + type: string + description: 'Platform to run on, can be macos or linux' + required: true + target-arch: + type: string + description: 'Arch to build for, can be x64, arm64 or arm' + required: true + test-runs-on: + type: string + description: 'What host to run the tests on' + required: true + test-container: + type: string + description: 'JSON container information for aks runs-on' + required: false + default: '{"image":null}' + is-asan: + description: 'Building the Address Sanitizer (ASan) Linux build' + required: false + type: boolean + default: false + +concurrency: + group: electron-test-${{ inputs.target-platform }}-${{ inputs.target-arch }}-${{ inputs.is-asan }}-${{ github.ref }} + cancel-in-progress: ${{ github.ref != 'refs/heads/main' && !endsWith(github.ref, '-x-y') }} + +permissions: + contents: read + issues: read + pull-requests: read + +env: + ELECTRON_OUT_DIR: Default + ELECTRON_RBE_JWT: ${{ secrets.ELECTRON_RBE_JWT }} + ELECTRON_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + +jobs: + test: + runs-on: ${{ inputs.test-runs-on }} + container: ${{ fromJSON(inputs.test-container) }} + strategy: + fail-fast: false + matrix: + build-type: ${{ inputs.target-platform == 'macos' && fromJSON('["darwin","mas"]') || fromJSON('["linux"]') }} + shard: ${{ inputs.target-platform == 'macos' && fromJSON('[1, 2]') || fromJSON('[1, 2, 3]') }} + env: + BUILD_TYPE: ${{ matrix.build-type }} + TARGET_ARCH: ${{ inputs.target-arch }} + ARTIFACT_KEY: ${{ matrix.build-type }}_${{ inputs.target-arch }} + steps: + - name: Fix node20 on arm32 runners + if: ${{ inputs.target-arch == 'arm' }} + run: | + cp $(which node) /mnt/runner-externals/node20/bin/ + - name: Add TCC permissions on macOS + if: ${{ inputs.target-platform == 'macos' }} + run: | + configure_user_tccdb () { + local values=$1 + local dbPath="$HOME/Library/Application Support/com.apple.TCC/TCC.db" + local sqlQuery="INSERT OR REPLACE INTO access VALUES($values);" + sqlite3 "$dbPath" "$sqlQuery" + } + + configure_sys_tccdb () { + local values=$1 + local dbPath="/Library/Application Support/com.apple.TCC/TCC.db" + local sqlQuery="INSERT OR REPLACE INTO access VALUES($values);" + sudo sqlite3 "$dbPath" "$sqlQuery" + } + + userValuesArray=( + "'kTCCServiceMicrophone','/usr/local/opt/runner/provisioner/provisioner',1,2,4,1,NULL,NULL,0,'UNUSED',NULL,0,1687786159" + "'kTCCServiceCamera','/usr/local/opt/runner/provisioner/provisioner',1,2,4,1,NULL,NULL,0,'UNUSED',NULL,0,1687786159" + "'kTCCServiceBluetoothAlways','/usr/local/opt/runner/provisioner/provisioner',1,2,4,1,NULL,NULL,0,'UNUSED',NULL,0,1687786159" + ) + for values in "${userValuesArray[@]}"; do + # Sonoma and higher have a few extra values + # Ref: https://github.com/actions/runner-images/blob/main/images/macos/scripts/build/configure-tccdb-macos.sh + if [ "$OSTYPE" = "darwin23" ]; then + configure_user_tccdb "$values,NULL,NULL,'UNUSED',${values##*,}" + configure_sys_tccdb "$values,NULL,NULL,'UNUSED',${values##*,}" + else + configure_user_tccdb "$values" + configure_sys_tccdb "$values" + fi + done + - name: Checkout Electron + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 + with: + path: src/electron + fetch-depth: 0 + - name: Install Dependencies + run: | + cd src/electron + node script/yarn install --frozen-lockfile + - name: Get Depot Tools + timeout-minutes: 5 + run: | + git clone --depth=1 https://chromium.googlesource.com/chromium/tools/depot_tools.git + if [ "`uname`" = "Darwin" ]; then + # remove ninjalog_uploader_wrapper.py from autoninja since we don't use it and it causes problems + sed -i '' '/ninjalog_uploader_wrapper.py/d' ./depot_tools/autoninja + else + sed -i '/ninjalog_uploader_wrapper.py/d' ./depot_tools/autoninja + # Remove swift-format dep from cipd on macOS until we send a patch upstream. + cd depot_tools + git apply --3way ../src/electron/.github/workflows/config/gclient.diff + fi + # Ensure depot_tools does not update. + test -d depot_tools && cd depot_tools + touch .disable_auto_update + - name: Add Depot Tools to PATH + run: echo "$(pwd)/depot_tools" >> $GITHUB_PATH + - name: Load ASan specific environment variables + if: ${{ inputs.is-asan == true }} + run: | + echo "ARTIFACT_KEY=${{ matrix.build-type }}_${{ inputs.target-arch }}_asan" >> $GITHUB_ENV + echo "DISABLE_CRASH_REPORTER_TESTS=true" >> $GITHUB_ENV + echo "IS_ASAN=true" >> $GITHUB_ENV + - name: Download Generated Artifacts + uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e + with: + name: generated_artifacts_${{ env.ARTIFACT_KEY }} + path: ./generated_artifacts_${{ matrix.build-type }}_${{ inputs.target-arch }} + - name: Download Src Artifacts + uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e + with: + name: src_artifacts_${{ env.ARTIFACT_KEY }} + path: ./src_artifacts_${{ matrix.build-type }}_${{ inputs.target-arch }} + - name: Restore Generated Artifacts + run: ./src/electron/script/actions/restore-artifacts.sh + - name: Unzip Dist, Mksnapshot & Chromedriver + run: | + cd src/out/Default + unzip -:o dist.zip + unzip -:o chromedriver.zip + unzip -:o mksnapshot.zip + - name: Import & Trust Self-Signed Codesigning Cert on MacOS + if: ${{ inputs.target-platform == 'macos' && inputs.target-arch == 'x64' }} + run: | + sudo security authorizationdb write com.apple.trust-settings.admin allow + cd src/electron + ./script/codesign/generate-identity.sh + - name: Run Electron Tests + shell: bash + env: + MOCHA_REPORTER: mocha-multi-reporters + ELECTRON_TEST_RESULTS_DIR: junit + MOCHA_MULTI_REPORTERS: mocha-junit-reporter, tap + ELECTRON_DISABLE_SECURITY_WARNINGS: 1 + ELECTRON_SKIP_NATIVE_MODULE_TESTS: true + DISPLAY: ':99.0' + run: | + cd src/electron + # Get which tests are on this shard + tests_files=$(node script/split-tests ${{ matrix.shard }} ${{ inputs.target-platform == 'macos' && 2 || 3 }}) + + # Run tests + if [ "`uname`" = "Darwin" ]; then + echo "About to start tests" + node script/yarn test --runners=main --trace-uncaught --enable-logging --files $tests_files + else + chown :builduser .. && chmod g+w .. + chown -R :builduser . && chmod -R g+w . + chmod 4755 ../out/Default/chrome-sandbox + runuser -u builduser -- git config --global --add safe.directory $(pwd) + if [ "${{ inputs.is-asan }}" == "true" ]; then + cd .. + ASAN_SYMBOLIZE="$PWD/tools/valgrind/asan/asan_symbolize.py --executable-path=$PWD/out/Default/electron" + export ASAN_OPTIONS="symbolize=0 handle_abort=1" + export G_SLICE=always-malloc + export NSS_DISABLE_ARENA_FREE_LIST=1 + export NSS_DISABLE_UNLOAD=1 + export LLVM_SYMBOLIZER_PATH=$PWD/third_party/llvm-build/Release+Asserts/bin/llvm-symbolizer + export MOCHA_TIMEOUT=180000 + echo "Piping output to ASAN_SYMBOLIZE ($ASAN_SYMBOLIZE)" + cd electron + runuser -u builduser -- xvfb-run script/actions/run-tests.sh script/yarn test --runners=main --trace-uncaught --enable-logging --files $tests_files | $ASAN_SYMBOLIZE + else + runuser -u builduser -- xvfb-run script/actions/run-tests.sh script/yarn test --runners=main --trace-uncaught --enable-logging --files $tests_files + fi + fi + - name: Wait for active SSH sessions + if: always() && !cancelled() + run: | + while [ -f /var/.ssh-lock ] + do + sleep 60 + done \ No newline at end of file diff --git a/.github/workflows/pipeline-segment-node-nan-test.yml b/.github/workflows/pipeline-segment-node-nan-test.yml new file mode 100644 index 000000000000..e87759878d4e --- /dev/null +++ b/.github/workflows/pipeline-segment-node-nan-test.yml @@ -0,0 +1,165 @@ +name: Pipeline Segment - Node/Nan Test + +on: + workflow_call: + inputs: + target-platform: + type: string + description: 'Platform to run on, can be macos or linux' + required: true + target-arch: + type: string + description: 'Arch to build for, can be x64, arm64 or arm' + required: true + test-runs-on: + type: string + description: 'What host to run the tests on' + required: true + test-container: + type: string + description: 'JSON container information for aks runs-on' + required: false + default: '{"image":null}' + gn-build-type: + description: 'The gn build type - testing or release' + required: true + type: string + default: testing + +concurrency: + group: electron-node-nan-test-${{ inputs.target-platform }}-${{ inputs.target-arch }}-${{ github.ref }} + cancel-in-progress: ${{ github.ref != 'refs/heads/main' && !endsWith(github.ref, '-x-y') }} + +env: + ELECTRON_OUT_DIR: Default + ELECTRON_RBE_JWT: ${{ secrets.ELECTRON_RBE_JWT }} + +jobs: + node-tests: + name: Run Node.js Tests + runs-on: aks-linux-medium-plus + timeout-minutes: 20 + env: + TARGET_ARCH: ${{ inputs.target-arch }} + BUILD_TYPE: linux + container: ${{ fromJSON(inputs.test-container) }} + steps: + - name: Checkout Electron + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 + with: + path: src/electron + fetch-depth: 0 + - name: Install Build Tools + uses: ./src/electron/.github/actions/install-build-tools + - name: Init Build Tools + run: | + e init -f --root=$(pwd) --out=Default ${{ inputs.gn-build-type }} --import ${{ inputs.gn-build-type }} --target-cpu ${{ inputs.target-arch }} + - name: Install Dependencies + run: | + cd src/electron + node script/yarn install --frozen-lockfile + - name: Get Depot Tools + timeout-minutes: 5 + run: | + git clone --depth=1 https://chromium.googlesource.com/chromium/tools/depot_tools.git + sed -i '/ninjalog_uploader_wrapper.py/d' ./depot_tools/autoninja + cd depot_tools + git apply --3way ../src/electron/.github/workflows/config/gclient.diff + # Ensure depot_tools does not update. + test -d depot_tools && cd depot_tools + touch .disable_auto_update + - name: Add Depot Tools to PATH + run: echo "$(pwd)/depot_tools" >> $GITHUB_PATH + - name: Download Generated Artifacts + uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e + with: + name: generated_artifacts_${{ env.BUILD_TYPE }}_${{ env.TARGET_ARCH }} + path: ./generated_artifacts_${{ env.BUILD_TYPE }}_${{ env.TARGET_ARCH }} + - name: Download Src Artifacts + uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e + with: + name: src_artifacts_linux_${{ env.TARGET_ARCH }} + path: ./src_artifacts_linux_${{ env.TARGET_ARCH }} + - name: Restore Generated Artifacts + run: ./src/electron/script/actions/restore-artifacts.sh + - name: Unzip Dist + run: | + cd src/out/Default + unzip -:o dist.zip + - name: Setup Linux for Headless Testing + run: sh -e /etc/init.d/xvfb start + - name: Run Node.js Tests + run: | + cd src + node electron/script/node-spec-runner.js --default --jUnitDir=junit + - name: Wait for active SSH sessions + if: always() && !cancelled() + run: | + while [ -f /var/.ssh-lock ] + do + sleep 60 + done + nan-tests: + name: Run Nan Tests + runs-on: aks-linux-medium + timeout-minutes: 20 + env: + TARGET_ARCH: ${{ inputs.target-arch }} + BUILD_TYPE: linux + container: ${{ fromJSON(inputs.test-container) }} + steps: + - name: Checkout Electron + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 + with: + path: src/electron + fetch-depth: 0 + - name: Install Build Tools + uses: ./src/electron/.github/actions/install-build-tools + - name: Init Build Tools + run: | + e init -f --root=$(pwd) --out=Default ${{ inputs.gn-build-type }} + - name: Install Dependencies + run: | + cd src/electron + node script/yarn install --frozen-lockfile + - name: Get Depot Tools + timeout-minutes: 5 + run: | + git clone --depth=1 https://chromium.googlesource.com/chromium/tools/depot_tools.git + sed -i '/ninjalog_uploader_wrapper.py/d' ./depot_tools/autoninja + cd depot_tools + git apply --3way ../src/electron/.github/workflows/config/gclient.diff + # Ensure depot_tools does not update. + test -d depot_tools && cd depot_tools + touch .disable_auto_update + - name: Add Depot Tools to PATH + run: echo "$(pwd)/depot_tools" >> $GITHUB_PATH + - name: Download Generated Artifacts + uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e + with: + name: generated_artifacts_${{ env.BUILD_TYPE }}_${{ env.TARGET_ARCH }} + path: ./generated_artifacts_${{ env.BUILD_TYPE }}_${{ env.TARGET_ARCH }} + - name: Download Src Artifacts + uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e + with: + name: src_artifacts_linux_${{ env.TARGET_ARCH }} + path: ./src_artifacts_linux_${{ env.TARGET_ARCH }} + - name: Restore Generated Artifacts + run: ./src/electron/script/actions/restore-artifacts.sh + - name: Unzip Dist + run: | + cd src/out/Default + unzip -:o dist.zip + - name: Setup Linux for Headless Testing + run: sh -e /etc/init.d/xvfb start + - name: Run Node.js Tests + run: | + cd src + node electron/script/nan-spec-runner.js + - name: Wait for active SSH sessions + if: always() && !cancelled() + run: | + while [ -f /var/.ssh-lock ] + do + sleep 60 + done \ No newline at end of file diff --git a/script/actions/move-artifacts.sh b/script/actions/move-artifacts.sh new file mode 100755 index 000000000000..70c8f75d4c29 --- /dev/null +++ b/script/actions/move-artifacts.sh @@ -0,0 +1,91 @@ +#!/bin/bash + +if [ "`uname`" == "Darwin" ]; then + if [ -z "$MAS_BUILD" ]; then + BUILD_TYPE="darwin" + else + BUILD_TYPE="mas" + fi +elif [ "`uname`" == "Linux" ]; then + BUILD_TYPE="linux" +else + echo "Unsupported platform" + exit 1 +fi + +GENERATED_ARTIFACTS="generated_artifacts_${BUILD_TYPE}_${TARGET_ARCH}" + +echo Creating $GENERATED_ARTIFACTS... +rm -rf $GENERATED_ARTIFACTS +mkdir $GENERATED_ARTIFACTS + +SRC_ARTIFACTS="src_artifacts_${BUILD_TYPE}_${TARGET_ARCH}" + +echo Creating $SRC_ARTIFACTS... +rm -rf $SRC_ARTIFACTS +mkdir $SRC_ARTIFACTS + +mv_if_exist() { + if [ -f "$1" ] || [ -d "$1" ]; then + echo Storing $1 + mv $1 $GENERATED_ARTIFACTS + else + echo Skipping $1 - It is not present on disk + fi +} + +cp_if_exist() { + if [ -f "$1" ] || [ -d "$1" ]; then + echo Storing $1 + cp $1 $GENERATED_ARTIFACTS + else + echo Skipping $1 - It is not present on disk + fi +} + +move_src_dirs_if_exist() { + mkdir src_artifacts + + for dir in \ + src/out/Default/gen/node_headers \ + src/out/Default/overlapped-checker \ + src/out/Default/ffmpeg \ + src/out/Default/hunspell_dictionaries \ + src/third_party/electron_node \ + src/third_party/nan \ + src/cross-arch-snapshots \ + src/third_party/llvm-build \ + src/build/linux \ + src/buildtools/mac \ + src/buildtools/third_party/libc++ \ + src/buildtools/third_party/libc++abi \ + src/third_party/libc++ \ + src/third_party/libc++abi \ + src/out/Default/obj/buildtools/third_party \ + src/v8/tools/builtins-pgo + do + if [ -d "$dir" ]; then + mkdir -p src_artifacts/$(dirname $dir) + cp -r $dir/ src_artifacts/$dir + fi + done + + tar -C src_artifacts -cf src_artifacts.tar ./ + + echo Storing src_artifacts.tar + mv src_artifacts.tar $SRC_ARTIFACTS +} + +# Generated Artifacts +mv_if_exist src/out/Default/dist.zip +mv_if_exist src/out/Default/gen/node_headers.tar.gz +mv_if_exist src/out/Default/symbols.zip +mv_if_exist src/out/Default/mksnapshot.zip +mv_if_exist src/out/Default/chromedriver.zip +mv_if_exist src/out/ffmpeg/ffmpeg.zip +mv_if_exist src/out/Default/hunspell_dictionaries.zip +mv_if_exist src/cross-arch-snapshots +cp_if_exist src/out/electron_ninja_log +cp_if_exist src/out/Default/.ninja_log + +move_src_dirs_if_exist \ No newline at end of file diff --git a/script/actions/restore-artifacts.sh b/script/actions/restore-artifacts.sh new file mode 100755 index 000000000000..dc70602d86bb --- /dev/null +++ b/script/actions/restore-artifacts.sh @@ -0,0 +1,40 @@ +#!/bin/bash + +GENERATED_ARTIFACTS="generated_artifacts_${BUILD_TYPE}_${TARGET_ARCH}" +SRC_ARTIFACTS="src_artifacts_${BUILD_TYPE}_${TARGET_ARCH}" + +mv_if_exist() { + if [ -f "${GENERATED_ARTIFACTS}/$1" ] || [ -d "${GENERATED_ARTIFACTS}/$1" ]; then + echo Restoring $1 to $2 + mkdir -p $2 + mv $GENERATED_ARTIFACTS/$1 $2 + else + echo Skipping $1 - It is not present on disk + fi +} + +untar_if_exist() { + if [ -f "${SRC_ARTIFACTS}/$1" ] || [ -d "${SRC_ARTIFACTS}/$1" ]; then + echo Restoring $1 to current directory + tar -xf ${SRC_ARTIFACTS}/$1 + else + echo Skipping $1 - It is not present on disk + fi +} + +echo Restoring artifacts from $GENERATED_ARTIFACTS + +# Restore generated artifacts +mv_if_exist dist.zip src/out/Default +mv_if_exist node_headers.tar.gz src/out/Default/gen +mv_if_exist symbols.zip src/out/Default +mv_if_exist mksnapshot.zip src/out/Default +mv_if_exist chromedriver.zip src/out/Default +mv_if_exist ffmpeg.zip src/out/ffmpeg +mv_if_exist hunspell_dictionaries.zip src/out/Default +mv_if_exist cross-arch-snapshots src + +echo Restoring artifacts from $SRC_ARTIFACTS + +# Restore src artifacts +untar_if_exist src_artifacts.tar \ No newline at end of file diff --git a/script/actions/run-tests.sh b/script/actions/run-tests.sh new file mode 100755 index 000000000000..7f68350bef6e --- /dev/null +++ b/script/actions/run-tests.sh @@ -0,0 +1,7 @@ +#!/bin/bash +set -euo pipefail + +export DISPLAY=:99 +Xvfb :99 -screen 0 1024x768x16 -ac & +XVFB_PID=$! +node "$@" \ No newline at end of file diff --git a/script/release/ci-release-build.js b/script/release/ci-release-build.js index 9e120ce2bbc8..0ceef891d8e1 100644 --- a/script/release/ci-release-build.js +++ b/script/release/ci-release-build.js @@ -9,11 +9,9 @@ const octokit = new Octokit({ }); const BUILD_APPVEYOR_URL = 'https://ci.appveyor.com/api/builds'; -const CIRCLECI_PIPELINE_URL = 'https://circleci.com/api/v2/project/gh/electron/electron/pipeline'; const GH_ACTIONS_PIPELINE_URL = 'https://github.com/electron/electron/actions'; const GH_ACTIONS_API_URL = '/repos/electron/electron/actions'; -const CIRCLECI_WAIT_TIME = process.env.CIRCLECI_WAIT_TIME || 30000; const GH_ACTIONS_WAIT_TIME = process.env.GH_ACTIONS_WAIT_TIME || 30000; const appVeyorJobs = { @@ -22,24 +20,11 @@ const appVeyorJobs = { 'electron-woa': 'electron-woa-release' }; -const circleCIPublishWorkflows = [ +const ghActionsPublishWorkflows = [ 'linux-publish', 'macos-publish' ]; -const circleCIPublishIndividualArches = { - 'macos-publish': ['osx-x64', 'mas-x64', 'osx-arm64', 'mas-arm64'], - 'linux-publish': ['arm', 'arm64', 'x64'] -}; - -const ghActionsPublishWorkflows = [ - 'macos-publish' -]; - -const ghActionsPublishIndividualArches = { - 'macos-publish': ['osx-x64', 'mas-x64', 'osx-arm64', 'mas-arm64'] -}; - let jobRequestedCount = 0; async function makeRequest ({ auth, username, password, url, headers, body, method }) { @@ -82,11 +67,6 @@ async function githubActionsCall (targetBranch, workflowName, options) { buildRequest.parameters['upload-to-storage'] = '1'; } buildRequest.parameters[`run-${workflowName}`] = true; - if (options.arch) { - const validArches = ghActionsPublishIndividualArches[workflowName]; - assert(validArches.includes(options.arch), `Unknown GitHub Actions architecture "${options.arch}". Valid values are ${JSON.stringify(validArches)}`); - buildRequest.parameters['macos-publish-arch-limit'] = options.arch; - } jobRequestedCount++; try { @@ -101,7 +81,7 @@ async function githubActionsCall (targetBranch, workflowName, options) { } await octokit.request(`POST ${GH_ACTIONS_API_URL}/workflows/${workflowName}.yml/dispatches`, { - ref: buildRequest.branch, + ref: `refs/tags/${options.newVersion}`, inputs: { ...buildRequest.parameters }, @@ -129,120 +109,6 @@ async function githubActionsCall (targetBranch, workflowName, options) { } } -async function circleCIcall (targetBranch, workflowName, options) { - console.log(`Triggering CircleCI to run build job: ${workflowName} on branch: ${targetBranch} with release flag.`); - const buildRequest = { - branch: targetBranch, - parameters: {} - }; - if (options.ghRelease) { - buildRequest.parameters['upload-to-storage'] = '0'; - } else { - buildRequest.parameters['upload-to-storage'] = '1'; - } - buildRequest.parameters[`run-${workflowName}`] = true; - if (options.arch) { - const validArches = circleCIPublishIndividualArches[workflowName]; - assert(validArches.includes(options.arch), `Unknown CircleCI architecture "${options.arch}". Valid values are ${JSON.stringify(validArches)}`); - buildRequest.parameters['macos-publish-arch-limit'] = options.arch; - } - - jobRequestedCount++; - // The logic below expects that the CircleCI workflows for releases each - // contain only one job in order to maintain compatibility with sudowoodo. - // If the workflows are changed in the CircleCI config.yml, this logic will - // also need to be changed as well as possibly changing sudowoodo. - try { - const circleResponse = await circleCIRequest(CIRCLECI_PIPELINE_URL, 'POST', buildRequest); - console.log(`CircleCI release build pipeline ${circleResponse.id} for ${workflowName} triggered.`); - const workflowId = await getCircleCIWorkflowId(circleResponse.id); - if (workflowId === -1) { - return; - } - const workFlowUrl = `https://circleci.com/workflow-run/${workflowId}`; - if (options.runningPublishWorkflows) { - console.log(`CircleCI release workflow request for ${workflowName} successful. Check ${workFlowUrl} for status.`); - } else { - console.log(`CircleCI release build workflow running at https://circleci.com/workflow-run/${workflowId} for ${workflowName}.`); - const jobNumber = await getCircleCIJobNumber(workflowId); - if (jobNumber === -1) { - return; - } - const jobUrl = `https://circleci.com/gh/electron/electron/${jobNumber}`; - console.log(`CircleCI release build request for ${workflowName} successful. Check ${jobUrl} for status.`); - } - } catch (err) { - console.log('Error calling CircleCI: ', err); - } -} - -async function getCircleCIWorkflowId (pipelineId) { - const pipelineInfoUrl = `https://circleci.com/api/v2/pipeline/${pipelineId}`; - let workflowId = 0; - while (workflowId === 0) { - const pipelineInfo = await circleCIRequest(pipelineInfoUrl, 'GET'); - switch (pipelineInfo.state) { - case 'created': { - const workflows = await circleCIRequest(`${pipelineInfoUrl}/workflow`, 'GET'); - // The logic below expects three workflow.items: publish, lint, & setup - if (workflows.items.length === 3) { - workflowId = workflows.items.find(item => item.name.includes('publish')).id; - break; - } - console.log('Unexpected number of workflows, response was:', workflows); - workflowId = -1; - break; - } - case 'error': { - console.log('Error retrieving workflows, response was:', pipelineInfo); - workflowId = -1; - break; - } - } - await new Promise(resolve => setTimeout(resolve, CIRCLECI_WAIT_TIME)); - } - return workflowId; -} - -async function getCircleCIJobNumber (workflowId) { - const jobInfoUrl = `https://circleci.com/api/v2/workflow/${workflowId}/job`; - let jobNumber = 0; - while (jobNumber === 0) { - const jobInfo = await circleCIRequest(jobInfoUrl, 'GET'); - if (!jobInfo.items) { - continue; - } - if (jobInfo.items.length !== 1) { - console.log('Unexpected number of jobs, response was:', jobInfo); - jobNumber = -1; - break; - } - - switch (jobInfo.items[0].status) { - case 'not_running': - case 'queued': - case 'running': { - if (jobInfo.items[0].job_number && !isNaN(jobInfo.items[0].job_number)) { - jobNumber = jobInfo.items[0].job_number; - } - break; - } - case 'canceled': - case 'error': - case 'infrastructure_fail': - case 'timedout': - case 'not_run': - case 'failed': { - console.log(`Error job returned a status of ${jobInfo.items[0].status}, response was:`, jobInfo); - jobNumber = -1; - break; - } - } - await new Promise(resolve => setTimeout(resolve, CIRCLECI_WAIT_TIME)); - } - return jobNumber; -} - async function getGitHubActionsRun (workflowId, headCommit) { let runNumber = 0; let actionRun; @@ -296,33 +162,6 @@ async function getGitHubActionsRun (workflowId, headCommit) { return runNumber; } -async function circleCIRequest (url, method, requestBody) { - const requestOpts = { - username: process.env.CIRCLE_TOKEN, - password: '', - method, - url, - headers: { - 'Content-Type': 'application/json', - Accept: 'application/json' - } - }; - if (requestBody) { - requestOpts.body = JSON.stringify(requestBody); - } - - return makeRequest(requestOpts, true).catch(err => { - if (err.response?.body) { - console.error('Could not call CircleCI: ', { - statusCode: err.response.statusCode, - body: JSON.parse(err.response.body) - }); - } else { - console.error('Error calling CircleCI:', err); - } - }); -} - async function callAppVeyor (targetBranch, job, options) { console.log(`Triggering AppVeyor to run build job: ${job} on branch: ${targetBranch} with release flag.`); const environmentVariables = { @@ -381,19 +220,6 @@ function buildAppVeyor (targetBranch, options) { } } -function buildCircleCI (targetBranch, options) { - if (options.job) { - assert(circleCIPublishWorkflows.includes(options.job), `Unknown CircleCI workflow name: ${options.job}. Valid values are: ${circleCIPublishWorkflows}.`); - circleCIcall(targetBranch, options.job, options); - } else { - assert(!options.arch, 'Cannot provide a single architecture while building all workflows, please specify a single workflow via --workflow'); - options.runningPublishWorkflows = true; - for (const job of circleCIPublishWorkflows) { - circleCIcall(targetBranch, job, options); - } - } -} - function buildGHActions (targetBranch, options) { if (options.job) { assert(ghActionsPublishWorkflows.includes(options.job), `Unknown GitHub Actions workflow name: ${options.job}. Valid values are: ${ghActionsPublishWorkflows}.`); @@ -410,10 +236,6 @@ function buildGHActions (targetBranch, options) { function runRelease (targetBranch, options) { if (options.ci) { switch (options.ci) { - case 'CircleCI': { - buildCircleCI(targetBranch, options); - break; - } case 'GitHubActions': { buildGHActions(targetBranch, options); break; @@ -428,10 +250,8 @@ function runRelease (targetBranch, options) { } } } else { - buildCircleCI(targetBranch, options); buildAppVeyor(targetBranch, options); - // TODO(vertedinde): Enable GH Actions in defaults when ready - // buildGHActions(targetBranch, options); + buildGHActions(targetBranch, options); } console.log(`${jobRequestedCount} jobs were requested.`); } @@ -445,8 +265,8 @@ if (require.main === module) { const targetBranch = args._[0]; if (args._.length < 1) { console.log(`Trigger CI to build release builds of electron. - Usage: ci-release-build.js [--job=CI_JOB_NAME] [--arch=INDIVIDUAL_ARCH] [--ci=CircleCI|AppVeyor|GitHubActions] - [--ghRelease] [--circleBuildNum=xxx] [--appveyorJobId=xxx] [--commit=sha] TARGET_BRANCH + Usage: ci-release-build.js [--job=CI_JOB_NAME] [--arch=INDIVIDUAL_ARCH] [--ci=AppVeyor|GitHubActions] + [--ghRelease] [--appveyorJobId=xxx] [--commit=sha] TARGET_BRANCH `); process.exit(0); } diff --git a/script/split-tests.js b/script/split-tests.js new file mode 100755 index 000000000000..43a039775815 --- /dev/null +++ b/script/split-tests.js @@ -0,0 +1,32 @@ +const fs = require('node:fs'); +const glob = require('glob'); + +const currentShard = parseInt(process.argv[2], 10); +const shardCount = parseInt(process.argv[3], 10); + +const specFiles = glob.sync('spec/*-spec.ts'); + +const buckets = []; + +for (let i = 0; i < shardCount; i++) { + buckets.push([]); +} + +const testsInSpecFile = Object.create(null); +for (const specFile of specFiles) { + const testContent = fs.readFileSync(specFile, 'utf8'); + testsInSpecFile[specFile] = testContent.split('it(').length; +} + +specFiles.sort((a, b) => { + return testsInSpecFile[b] - testsInSpecFile[a]; +}); + +let shard = 0; +for (const specFile of specFiles) { + buckets[shard].push(specFile); + shard++; + if (shard === shardCount) shard = 0; +} + +console.log(buckets[currentShard - 1].join(' ')); diff --git a/spec/api-app-spec.ts b/spec/api-app-spec.ts index c1eb84b24718..6fd2b76406fa 100644 --- a/spec/api-app-spec.ts +++ b/spec/api-app-spec.ts @@ -595,7 +595,7 @@ describe('app module', () => { }); }); - ifdescribe(process.platform !== 'linux' && !process.mas)('app.get/setLoginItemSettings API', function () { + ifdescribe(process.platform !== 'linux' && !process.mas && (process.platform !== 'darwin' || process.arch === 'arm64'))('app.get/setLoginItemSettings API', function () { const isMac = process.platform === 'darwin'; const isWin = process.platform === 'win32'; diff --git a/spec/api-protocol-spec.ts b/spec/api-protocol-spec.ts index 122cc4e84f0d..3ba77351d839 100644 --- a/spec/api-protocol-spec.ts +++ b/spec/api-protocol-spec.ts @@ -1749,7 +1749,7 @@ describe('protocol module', () => { const end = Date.now(); return end - begin; })(); - expect(interceptedTime).to.be.lessThan(rawTime * 1.5); + expect(interceptedTime).to.be.lessThan(rawTime * 1.6); }); }); });