Browse Source

build: add GitHub Actions publishing pipeline for macOS (#42236)

* build: add publishing workflow for GHActions

* build: add test repo/bucket for uploads

* build: clean up conditionals, add macos-14-large, review comments

* build: remove host_cpu var from GCLIENT_EXTRA_ARGS
Keeley Hammond 10 months ago
parent
commit
361b37592a

+ 0 - 1
.github/workflows/config/evm.mas.json

@@ -9,7 +9,6 @@
     "args": [
       "import(\"//electron/build/args/testing.gn\")",
       "use_remoteexec = true",
-      "target_cpu = \"arm64\"",
       "is_mas_build = true"
     ],
     "out": "Default"

+ 269 - 57
.github/workflows/macos-build.yml

@@ -3,41 +3,60 @@ name: Build MacOS
 # TODO: change to 'pull_request' and 'push' 
 # when we are ready to enable this for PRs.
 on:
-  workflow_dispatch:
+  workflow_call:
+    inputs:
+      IS_RELEASE:
+        required: true
+        type: boolean
+        default: false
+      GN_CONFIG:
+        required: false
+        type: string
+        default: //electron/build/args/testing.gn
+      GN_BUILD_TYPE:
+        required: false
+        type: string
+        default: testing
+      GENERATE_SYMBOLS: 
+        required: false
+        type: boolean
+        default: false
+      UPLOAD_TO_STORAGE: 
+        required: false
+        type: string
+        default: '0'
+      
 
 concurrency:
   group: ${{ github.workflow }}-${{ github.ref }}
   cancel-in-progress: true
 
 env:
-  GCLIENT_EXTRA_ARGS: '--custom-var=checkout_mac=True --custom-var=host_os=mac --custom-var=host_cpu=arm64'
-  IS_RELEASE: false
-  # GENERATE_SYMBOLS: true only on release builds
-  GENERATE_SYMBOLS: false
   AZURE_STORAGE_ACCOUNT: ${{ secrets.AZURE_STORAGE_ACCOUNT }}
   AZURE_STORAGE_KEY: ${{ secrets.AZURE_STORAGE_KEY }}
   AZURE_STORAGE_CONTAINER_NAME: ${{ secrets.AZURE_STORAGE_CONTAINER_NAME }}
   ELECTRON_RBE_JWT: ${{ secrets.ELECTRON_RBE_JWT }}
-  # TODO: this should be set to the correct GN_CONFIG for the build type.
-  GN_CONFIG: //electron/build/args/testing.gn
   # Disable pre-compiled headers to reduce out size - only useful for rebuilds
   GN_BUILDFLAG_ARGS: 'enable_precompiled_headers = false'
+  GCLIENT_EXTRA_ARGS: '--custom-var=checkout_mac=True --custom-var=host_os=mac'
+  CHECK_DIST_MANIFEST: '1'
+  IS_GHA_RELEASE: true
 
 jobs:
   checkout:
     runs-on: LargeLinuxRunner
     steps:
     - name: Checkout Electron
-      uses: actions/checkout@v4
+      uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b
       with:
         path: src/electron
     - name: Install Azure CLI
-      run: ./script/azure_cli_deb_install.sh
+      run: sudo bash ./src/electron/script/azure_cli_deb_install.sh
     - name: Set GIT_CACHE_PATH to make gclient to use the cache
       run: |
         echo "GIT_CACHE_PATH=$(pwd)/git-cache" >> $GITHUB_ENV
     - name: Setup Node.js/npm
-      uses: actions/setup-node@v3
+      uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8
       with:
         node-version: 20.11.x
         cache: yarn
@@ -97,7 +116,7 @@ jobs:
           "$GITHUB_SERVER_URL/$GITHUB_REPOSITORY"
 
         ELECTRON_USE_THREE_WAY_MERGE_FOR_PATCHES=1 gclient sync --with_branch_heads --with_tags -vvvvv
-        if [ "$IS_RELEASE" != "true" ]; then
+        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
@@ -168,23 +187,29 @@ jobs:
           --name $DEPSHASH \
           --debug
   build:
-    runs-on: macos-13-xlarge
+    strategy:
+      fail-fast: false
+      # macos-large is x64, macos-xlarge is arm64
+      # More runner information: https://github.com/actions/runner-images/blob/main/README.md#available-images
+      matrix:
+        arch: [ macos-14-large, macos-14-xlarge ]
+    runs-on: ${{ matrix.arch }}
     needs: checkout
     steps:
     - name: Load Build Tools
       run: |
         export BUILD_TOOLS_SHA=2bb63e2e7877491b52f972532b52adc979a6ec2f
         npm i -g @electron/build-tools
-        e init --root=$(pwd) --out=Default testing
+        e init --root=$(pwd) --out=Default ${{ inputs.GN_BUILD_TYPE }}
     - name: Checkout Electron
-      uses: actions/checkout@v4
+      uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b
       with:
         path: src/electron
     - name: Install Azure CLI
       run: |
         brew update && brew install azure-cli
     - name: Setup Node.js/npm
-      uses: actions/setup-node@v3
+      uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8
       with:
         node-version: 20.11.x
         cache: yarn
@@ -193,6 +218,18 @@ jobs:
       run: |
         cd src/electron
         node script/yarn install
+    - name: Load Target Arch & CPU
+      run: |
+        ARCH=$(uname -m)
+        if [ "$ARCH" == "x86_64" ]; then
+          echo "TARGET_ARCH="x64"" >> $GITHUB_ENV
+          echo "target_cpu="x64"" >> $GITHUB_ENV
+          echo "host_cpu="x64"" >> $GITHUB_ENV
+        else
+          echo "TARGET_ARCH="arm64"" >> $GITHUB_ENV
+          echo "target_cpu="arm64"" >> $GITHUB_ENV
+          echo "host_cpu="arm64"" >> $GITHUB_ENV
+        fi
     - name: Get Depot Tools
       timeout-minutes: 5
       run: |
@@ -250,7 +287,7 @@ jobs:
         echo "Wiping Electron Directory"
         rm -rf src/electron
     - name: Checkout Electron
-      uses: actions/checkout@v4
+      uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b
       with:
         path: src/electron
     - name: Run Electron Only Hooks
@@ -326,6 +363,91 @@ jobs:
         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 Space on MacOS
+      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
+
+        # the contents of build/linux/strip_binary.gni aren't used, but
+        # https://chromium-review.googlesource.com/c/chromium/src/+/4278307
+        # needs the file to exist.
+        # mv ~/project/src/build/linux/strip_binary.gni "${TMPDIR}"/
+        # tmpify ~/project/src/build/linux/
+        # mkdir -p ~/project/src/build/linux
+        # mv "${TMPDIR}/strip_binary.gni" ~/project/src/build/linux/
+
+        sudo rm -rf $TMPDIR/del-target
+
+        # sudo rm -rf "/System/Library/Desktop Pictures"
+        # sudo rm -rf /System/Library/Templates/Data
+        # sudo rm -rf /System/Library/Speech/Voices
+        # sudo rm -rf "/System/Library/Screen Savers"
+        # sudo rm -rf /System/Volumes/Data/Library/Developer/CommandLineTools/SDKs
+        # sudo rm -rf "/System/Volumes/Data/Library/Application Support/Apple/Photos/Print Products"
+        # sudo rm -rf /System/Volumes/Data/Library/Developer/CommandLineTools/SDKs/MacOSX10.15.sdk/
+        # sudo rm -rf /System/Volumes/Data/Library/Java
+        # sudo rm -rf /System/Volumes/Data/Library/Ruby
+        # sudo rm -rf /System/Volumes/Data/Library/Printers
+        # sudo rm -rf /System/iOSSupport
+        # sudo rm -rf /System/Applications/*.app
+        # sudo rm -rf /System/Applications/Utilities/*.app
+        # sudo rm -rf /System/Library/LinguisticData
+        # sudo rm -rf /System/Volumes/Data/private/var/db/dyld/*
+        # sudo rm -rf /System/Library/Fonts/*
+        # sudo rm -rf /System/Library/PreferencePanes
+        # sudo rm -rf /System/Library/AssetsV2/*
+        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
     - name: Build Electron (darwin)
       run: |
         cd src/electron
@@ -341,11 +463,10 @@ jobs:
     - name: Build Electron dist.zip (darwin)
       run: |
         cd src
-        e build electron:electron_dist_zip $ADDITIONAL_TARGETS -j $NUMBER_OF_NINJA_PROCESSES
+        e build electron:electron_dist_zip -j $NUMBER_OF_NINJA_PROCESSES
         if [ "$CHECK_DIST_MANIFEST" == "1" ]; then
           target_os=mac
-          target_cpu=arm64
-          electron/script/zip_manifests/check-zip-manifest.py out/Default/dist.zip electron/script/zip_manifests/dist_zip.$target_os.$target_cpu.manifest
+          electron/script/zip_manifests/check-zip-manifest.py out/Default/dist.zip electron/script/zip_manifests/dist_zip.$target_os.${{ env.TARGET_ARCH }}.manifest
         fi
     - name: Build Mksnapshot (darwin)
       run: |
@@ -357,41 +478,56 @@ jobs:
         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 [ "$SKIP_DIST_ZIP" != "1" ]; then
-          e build electron:electron_mksnapshot_zip -j $NUMBER_OF_NINJA_PROCESSES
-          (cd out/Default; zip mksnapshot.zip mksnapshot_args gen/v8/embedded.S)
-        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: Build Chromedriver (darwin)
       run: |
         cd src
         e build electron:electron_chromedriver -j $NUMBER_OF_NINJA_PROCESSES
         e build electron:electron_chromedriver_zip
-    - name: Build Node Headers (darwin)
-      run: |
-        cd src
-        e build electron:node_headers
+    # NOTE (vertedinde): We strip binaries/symbols on the Linux job, not the Mac job
     - name: Generate & Zip Symbols (darwin)
       run: |
-        if [ "$GENERATE_SYMBOLS" == "true" ]; then
+        # 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
-        electron/script/zip-symbols.py -b $BUILD_PATH
-      # TODO(vertedinde): handle creating ffmpeg and hunspell for release builds
-      # The current generated_artifacts_<< artifact.key >> name was taken from CircleCI
-      # tp ensure we don't break anything, but we may be able to improve that.
+        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
+      if: github.event.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
+      if: github.event.inputs.IS_RELEASE == 'true'
+      run: |
+        cd src
+        autoninja -C out/Default electron:hunspell_dictionaries_zip -j $NUMBER_OF_NINJA_PROCESSES
+    - name: Generate TypeScript Definitions
+      if: github.event.inputs.IS_RELEASE == 'true'
+      run: |
+        cd src/electron
+        node script/yarn create-typescript-definitions
+    # 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
       run: ./src/electron/script/actions/move-artifacts.sh
     - name: Upload Generated Artifacts
-      uses: actions/upload-artifact@v4
+      uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808
       with:
-        name: generated_artifacts_darwin
-        path: ./generated_artifacts_darwin
+        name: generated_artifacts_darwin_${{ env.TARGET_ARCH }}
+        path: ./generated_artifacts_darwin_${{ env.TARGET_ARCH }}
     - name: Persist Build Artifacts
-      uses: actions/cache/save@v4
+      uses: actions/cache/save@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9
       with:
         path: |
           src/out/Default/gen/node_headers
@@ -409,7 +545,7 @@ jobs:
           src/third_party/libc++abi
           src/out/Default/obj/buildtools/third_party
           src/v8/tools/builtins-pgo
-        key: ${{ runner.os }}-build-artifacts-darwin-${{ github.sha }}
+        key: ${{ runner.os }}-build-artifacts-darwin-${{ env.TARGET_ARCH }}-${{ github.sha }}
     - name: Create MAS Config
       run: |
         mv src/electron/.github/workflows/config/evm.mas.json $HOME/.electron_build_tools/configs/evm.mas.json
@@ -433,11 +569,10 @@ jobs:
     - name: Build Electron dist.zip (mas)
       run: |
         cd src
-        e build electron:electron_dist_zip $ADDITIONAL_TARGETS -j $NUMBER_OF_NINJA_PROCESSES
+        e build electron:electron_dist_zip -j $NUMBER_OF_NINJA_PROCESSES
         if [ "$CHECK_DIST_MANIFEST" == "1" ]; then
           target_os=mac_mas
-          target_cpu=arm64
-          electron/script/zip_manifests/check-zip-manifest.py out/Default/dist.zip electron/script/zip_manifests/dist_zip.$target_os.$target_cpu.manifest
+          electron/script/zip_manifests/check-zip-manifest.py out/Default/dist.zip electron/script/zip_manifests/dist_zip.$target_os.${{ env.TARGET_ARCH }}.manifest
         fi
     - name: Build Mksnapshot (mas)
       run: |
@@ -449,10 +584,8 @@ jobs:
         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 [ "$SKIP_DIST_ZIP" != "1" ]; then
-          e build electron:electron_mksnapshot_zip -j $NUMBER_OF_NINJA_PROCESSES
-          (cd out/Default; zip mksnapshot.zip mksnapshot_args gen/v8/embedded.S)
-        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: Build Chromedriver (mas)
       run: |
         cd src
@@ -464,27 +597,33 @@ jobs:
         e build electron:node_headers
     - name: Generate & Zip Symbols (mas)
       run: |
-        if [ "$GENERATE_SYMBOLS" == "true" ]; then
+        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
-        electron/script/zip-symbols.py -b $BUILD_PATH
+        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: Move all Generated Artifacts to Upload Folder (mas)
       run: ./src/electron/script/actions/move-artifacts.sh
     - name: Upload Generated Artifacts
-      uses: actions/upload-artifact@v4
+      uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808
       with:
-        name: generated_artifacts_mas
-        path: ./generated_artifacts_mas
+        name: generated_artifacts_mas_${{ env.TARGET_ARCH }}
+        path: ./generated_artifacts_mas_${{ env.TARGET_ARCH }}
     - name: Persist Build Artifacts
-      uses: actions/cache/save@v4
+      uses: actions/cache/save@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9
       with:
         path: |
           src/out/Default/gen/node_headers
           src/out/Default/overlapped-checker
+          src/out/Default/ffmpeg
+          src/out/Default/hunspell_dictionaries
           src/electron
           src/third_party/electron_node
           src/third_party/nan
@@ -498,9 +637,77 @@ jobs:
           src/third_party/libc++abi
           src/out/Default/obj/buildtools/third_party
           src/v8/tools/builtins-pgo
-        key: ${{ runner.os }}-build-artifacts-mas-${{ github.sha }}
+        key: ${{ runner.os }}-build-artifacts-mas-${{ env.TARGET_ARCH }}-${{ github.sha }}
+  upload:
+    runs-on: LargeLinuxRunner
+    if: ${{ inputs.IS_RELEASE == true }}
+    needs: build
+    strategy:
+      fail-fast: false
+      matrix:
+        build-type: [darwin, mas]
+        arch: [x64, arm64]
+    steps:
+    - name: Checkout Electron
+      uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b
+      with:
+        path: src/electron
+    - name: Setup Node.js/npm
+      uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8
+      with:
+        node-version: 20.11.x
+        cache: yarn
+        cache-dependency-path: src/electron/yarn.lock
+    - name: Load Target Arch
+      run: echo "TARGET_ARCH=${{ matrix.arch }}" >> $GITHUB_ENV
+    - name: Install Dependencies
+      run: |
+        cd src/electron
+        node script/yarn install
+    - name: Download Generated Artifacts
+      uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e 
+      with:
+        name: generated_artifacts_${{ matrix.build-type }}_${{ matrix.arch }}
+        path: ./generated_artifacts_${{ matrix.build-type }}_${{ matrix.arch }}
+    - name: Restore Persisted Build Artifacts
+      uses: actions/cache/restore@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9
+      with:
+        path: |
+          src/out/Default/gen/node_headers
+          src/out/Default/overlapped-checker
+          src/out/Default/ffmpeg
+          src/out/Default/hunspell_dictionaries
+          src/electron
+          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
+        key: macOS-build-artifacts-${{ matrix.build-type }}-${{ matrix.arch }}-${{ github.sha }}
+    - name: Restore Generated Artifacts
+      run: ./src/electron/script/actions/restore-artifacts.sh
+    # TODO(vertedinde): These uploads currently point to a different Azure bucket & GitHub Repo
+    - name: Publish Electron Dist
+      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
   test:
-    runs-on: macos-13-xlarge
+    if: ${{ inputs.IS_RELEASE == false }}
+    runs-on: macos-14-xlarge
     needs: build
     strategy:
       fail-fast: false
@@ -512,13 +719,13 @@ jobs:
     - name: Load Build Tools
       run: |
         yarn add git://github.com/electron/build-tools.git#2bb63e2e7877491b52f972532b52adc979a6ec2f
-        e init --root=$(pwd) --out=Default testing
+        e init --root=$(pwd) --out=Default ${{ inputs.GN_BUILD_TYPE }}
     - name: Checkout Electron
-      uses: actions/checkout@v4
+      uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b
       with:
         path: src/electron
     - name: Setup Node.js/npm
-      uses: actions/setup-node@v3
+      uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8
       with:
         node-version: 20.11.x
         cache: yarn
@@ -546,12 +753,12 @@ jobs:
     - name: Add Depot Tools to PATH
       run: echo "$(pwd)/depot_tools" >> $GITHUB_PATH
     - name: Download Generated Artifacts
-      uses: actions/download-artifact@v4
+      uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e
       with:
         name: generated_artifacts_${{ matrix.build-type }}
         path: ./generated_artifacts_${{ matrix.build-type }}
     - name: Restore Persisted Build Artifacts
-      uses: actions/cache/restore@v4
+      uses: actions/cache/restore@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9
       with:
         path: |
           src/out/Default/gen/node_headers
@@ -578,6 +785,11 @@ jobs:
         unzip -:o dist.zip
         unzip -:o chromedriver.zip
         unzip -:o mksnapshot.zip
+    - name: Import & Trust Self-Signed Codesigning Cert on MacOS
+      run: |
+        sudo security authorizationdb write com.apple.trust-settings.admin allow
+        cd src/electron
+        ./script/codesign/generate-identity.sh
     - name: Run Electron Tests
       env:
         MOCHA_REPORTER: mocha-multi-reporters

+ 26 - 0
.github/workflows/macos-publish.yml

@@ -0,0 +1,26 @@
+name: Publish MacOS
+
+on:
+  workflow_dispatch:
+    inputs:
+      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:
+  publish:
+  # TODO(vertedinde): Change this to main before merge
+    uses: electron/electron/.github/workflows/macos-build.yml@gh-actions-mac-publish
+    with:
+      IS_RELEASE: true
+      GN_CONFIG: //electron/build/args/release.gn
+      GN_BUILD_TYPE: release
+      GENERATE_SYMBOLS: true
+      UPLOAD_TO_STORAGE: ${{ inputs.upload-to-storage }}
+    secrets: inherit

+ 5 - 4
script/actions/move-artifacts.sh

@@ -8,13 +8,14 @@ else
   BUILD_TYPE="mas"
 fi
 
-rm -rf generated_artifacts_${BUILD_TYPE}
-mkdir generated_artifacts_${BUILD_TYPE}
+echo Creating generated_artifacts_${BUILD_TYPE}_${TARGET_ARCH}...
+rm -rf generated_artifacts_${BUILD_TYPE}_${TARGET_ARCH}
+mkdir generated_artifacts_${BUILD_TYPE}_${TARGET_ARCH}
 
 mv_if_exist() {
   if [ -f "$1" ] || [ -d "$1" ]; then
     echo Storing $1
-    mv $1 generated_artifacts_${BUILD_TYPE}
+    mv $1 generated_artifacts_${BUILD_TYPE}_${TARGET_ARCH}
   else
     echo Skipping $1 - It is not present on disk
   fi
@@ -22,7 +23,7 @@ mv_if_exist() {
 cp_if_exist() {
   if [ -f "$1" ] || [ -d "$1" ]; then
     echo Storing $1
-    cp $1 generated_artifacts_${BUILD_TYPE}
+    cp $1 generated_artifacts_${BUILD_TYPE}_${TARGET_ARCH}
   else
     echo Skipping $1 - It is not present on disk
   fi

+ 3 - 3
script/actions/restore-artifacts.sh

@@ -1,12 +1,12 @@
-#!/bin/sh
+#!/bin/bash
 
 set -eo pipefail
 
 mv_if_exist() {
-  if [ -f "generated_artifacts_${BUILD_TYPE}/$1" ] || [ -d "generated_artifacts_${BUILD_TYPE}/$1" ]; then
+  if [ -f "generated_artifacts_${BUILD_TYPE}_${TARGET_ARCH}/$1" ] || [ -d "generated_artifacts_${BUILD_TYPE}_${TARGET_ARCH}/$1" ]; then
     echo Restoring $1 to $2
     mkdir -p $2
-    mv generated_artifacts_${BUILD_TYPE}/$1 $2
+    mv generated_artifacts_${BUILD_TYPE_${TARGET_ARCH}}/$1 $2
   else
     echo Skipping $1 - It is not present on disk
   fi

+ 3 - 0
script/lib/azput.js

@@ -2,6 +2,9 @@
 const { BlobServiceClient } = require('@azure/storage-blob');
 const path = require('node:path');
 
+// TODO(vertedinde): This variable is a test variable in GHA, sending test
+// artifacts to a test account. Change to the real electron artifacts
+// storage account when ready.
 const blobServiceClient = BlobServiceClient.fromConnectionString(process.env.ELECTRON_ARTIFACTS_BLOB_STORAGE);
 
 const args = require('minimist')(process.argv.slice(2));

+ 1 - 11
script/release/ci-release-build.js

@@ -36,10 +36,6 @@ 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 +78,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 {
@@ -430,8 +421,7 @@ 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.`);
 }

+ 7 - 1
script/release/find-github-release.js

@@ -11,11 +11,17 @@ if (process.argv.length < 3) {
 }
 
 const version = process.argv[2];
+const targetRepo = findRepo();
+
+function findRepo () {
+  if (process.env.IS_GHA_RELEASE) return 'test-releases';
+  else return version.indexOf('nightly') > 0 ? 'nightlies' : 'electron';
+}
 
 async function findRelease () {
   const releases = await octokit.repos.listReleases({
     owner: 'electron',
-    repo: version.indexOf('nightly') > 0 ? 'nightlies' : 'electron'
+    repo: targetRepo
   });
 
   const targetRelease = releases.data.find(release => release.tag_name === version);

+ 6 - 1
script/release/prepare-release.js

@@ -14,7 +14,12 @@ const readline = require('node:readline');
 const releaseNotesGenerator = require('./notes/index.js');
 const { getCurrentBranch, ELECTRON_DIR } = require('../lib/utils.js');
 const bumpType = args._[0];
-const targetRepo = bumpType === 'nightly' ? 'nightlies' : 'electron';
+const targetRepo = getRepo();
+
+function getRepo () {
+  if (process.env.IS_GHA_RELEASE) return 'test-releases';
+  return bumpType === 'nightly' ? 'nightlies' : 'electron';
+}
 
 const octokit = new Octokit({
   auth: process.env.ELECTRON_GITHUB_TOKEN

+ 9 - 3
script/release/publish-to-npm.js

@@ -45,6 +45,12 @@ let npmTag = '';
 
 const currentElectronVersion = getElectronVersion();
 const isNightlyElectronVersion = currentElectronVersion.includes('nightly');
+const targetRepo = getRepo();
+
+function getRepo () {
+  if (process.env.IS_GHA_RELEASE) return 'test-releases';
+  return isNightlyElectronVersion ? 'nightlies' : 'electron';
+}
 
 new Promise((resolve, reject) => {
   temp.mkdir('electron-npm', (err, dirPath) => {
@@ -78,7 +84,7 @@ new Promise((resolve, reject) => {
 
     return octokit.repos.listReleases({
       owner: 'electron',
-      repo: isNightlyElectronVersion ? 'nightlies' : 'electron'
+      repo: targetRepo
     });
   })
   .then((releases) => {
@@ -98,7 +104,7 @@ new Promise((resolve, reject) => {
     }
 
     const typingsContent = await getAssetContents(
-      isNightlyElectronVersion ? 'nightlies' : 'electron',
+      targetRepo,
       tsdAsset.id
     );
 
@@ -113,7 +119,7 @@ new Promise((resolve, reject) => {
     }
 
     const checksumsContent = await getAssetContents(
-      isNightlyElectronVersion ? 'nightlies' : 'electron',
+      targetRepo,
       checksumsAsset.id
     );
 

+ 6 - 1
script/release/release.js

@@ -32,7 +32,12 @@ const octokit = new Octokit({
   auth: process.env.ELECTRON_GITHUB_TOKEN
 });
 
-const targetRepo = pkgVersion.indexOf('nightly') > 0 ? 'nightlies' : 'electron';
+function getRepo () {
+  if (process.env.IS_GHA_RELEASE) return 'test-releases';
+  return pkgVersion.indexOf('nightly') > 0 ? 'nightlies' : 'electron';
+}
+
+const targetRepo = getRepo();
 let failureCount = 0;
 
 async function getDraftRelease (version, skipValidation) {

+ 6 - 1
script/release/uploaders/upload-to-github.ts

@@ -43,7 +43,12 @@ const getHeaders = (filePath: string, fileName: string) => {
   };
 };
 
-const targetRepo = releaseVersion.indexOf('nightly') > 0 ? 'nightlies' : 'electron';
+function getRepo () {
+  if (process.env.IS_GHA_RELEASE) return 'test-releases';
+  return releaseVersion.indexOf('nightly') > 0 ? 'nightlies' : 'electron';
+}
+
+const targetRepo = getRepo();
 const uploadUrl = `https://uploads.github.com/repos/electron/${targetRepo}/releases/${releaseId}/assets{?name,label}`;
 let retry = 0;