This is an automated email from the ASF dual-hosted git repository.
amoeba pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow.git
The following commit(s) were added to refs/heads/main by this push:
new 9265a71614 GH-49537: [C++][FlightRPC] Windows CI to Support ODBC DLL &
MSI Signing (#49603)
9265a71614 is described below
commit 9265a71614a9552590e59b786af9355573d01133
Author: Alina (Xi) Li <[email protected]>
AuthorDate: Tue Jun 9 14:59:25 2026 -0700
GH-49537: [C++][FlightRPC] Windows CI to Support ODBC DLL & MSI Signing
(#49603)
### Rationale for this change
GH-49537
### What changes are included in this PR?
- Implement Windows CIs to:
1. CI A - `odbc-msvc-upload-dll` Upload unsigned DLL
2. CI B - `odbc-msvc-upload-msi` Download signed DLL and upload
unsigned MSI
- Remove `odbc-release` CI that is replaced by the new CIs.
- Use composite action to reuse code for building ODBC Windows.
- The release manager can run CI A first, then download the unsigned DLL
and upload signed DLL.
- Run CI B to upload unsigned MSI. Then sign the MSI locally, and upload
signed MSI to GitHub release. Example Command to trigger CI B:
```
gh workflow run cpp_extra.yml --ref apache-arrow-test-24.0.0-rc0 -f
odbc_release_step=true
```
Example of `07-flightsqlodbc-upload.sh` script (not tested):
We need to either 1) implement a way to get `RUN_ID` and then call `gh run
watch`,
or 2) enter each command manually and wait for the CI to finish.
```
# download unsigned DLL
gh release download $tag --pattern arrow_flight_sql_odbc_unsigned.dll
# sign ODBC DLL and upload to GitHub release
jsign arrow_flight_sql_odbc_unsigned.dll ...
mv arrow_flight_sql_odbc_unsigned.dll arrow_flight_sql_odbc.dll
gh release upload $tag --clobber arrow_flight_sql_odbc.dll
# trigger CI B
gh workflow run cpp_extra.yml --ref $tag -f odbc_upload=msi
# download unsigned MSI
gh release download $tag --pattern Apache-Arrow-Flight-SQL-ODBC-*-win64.msi
# sign ODBC MSI and upload to GitHub release
jsign Apache-Arrow-Flight-SQL-ODBC-*-win64.msi ...
gh release upload $tag --clobber Apache-Arrow-Flight-SQL-ODBC-*-win64.msi
# remove ODBC DLLs from GitHub release
gh release delete-asset $tag arrow_flight_sql_odbc_unsigned.dll --yes
gh release delete-asset $tag arrow_flight_sql_odbc.dll --yes
```
Documentation is in:
https://github.com/apache/arrow/blob/62cdda9cb79a5d5e5e188b0aeb42316431eecc85/docs/source/developers/release.rst?plain=1#L267-L276
### Are these changes tested?
- The uploading and signing process is tested in my repo
- Workflows are verified in CI
### Are there any user-facing changes?
N/A
* GitHub Issue: #49537
Authored-by: Alina (Xi) Li <[email protected]>
Signed-off-by: Bryce Mecum <[email protected]>
---
.github/actions/odbc-windows/action.yml | 96 +++++++++++++++++
.github/workflows/cpp_extra.yml | 113 +-------------------
.github/workflows/package_odbc.yml | 178 ++++++++++++++++++++++++++++++++
dev/release/07-flightsqlodbc-upload.sh | 20 ++--
4 files changed, 288 insertions(+), 119 deletions(-)
diff --git a/.github/actions/odbc-windows/action.yml
b/.github/actions/odbc-windows/action.yml
new file mode 100644
index 0000000000..153fccceef
--- /dev/null
+++ b/.github/actions/odbc-windows/action.yml
@@ -0,0 +1,96 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+name: ODBC Windows Reusable
+inputs:
+ github-token:
+ description: 'GITHUB_TOKEN for vcpkg caching'
+ required: true
+runs:
+ using: "composite"
+ steps:
+ - name: Disable Crash Dialogs
+ shell: pwsh
+ run: |
+ reg add `
+ "HKCU\SOFTWARE\Microsoft\Windows\Windows Error Reporting" `
+ /v DontShowUI `
+ /t REG_DWORD `
+ /d 1 `
+ /f
+ - name: Download Timezone Database
+ shell: bash
+ run: ci/scripts/download_tz_database.sh
+ - name: Install ccache
+ shell: bash
+ run: |
+ ci/scripts/install_ccache.sh 4.12.1 /usr
+ - name: Setup ccache
+ shell: bash
+ run: |
+ ci/scripts/ccache_setup.sh
+ - name: ccache info
+ id: ccache-info
+ shell: bash
+ run: |
+ echo "cache-dir=$(ccache --get-config cache_dir)" >> $GITHUB_OUTPUT
+ - name: Cache ccache
+ uses: actions/cache@v5
+ with:
+ path: ${{ steps.ccache-info.outputs.cache-dir }}
+ key: cpp-odbc-ccache-windows-x64-${{ hashFiles('cpp/**') }}
+ restore-keys: cpp-odbc-ccache-windows-x64-
+ - name: Checkout vcpkg
+ uses: actions/checkout@v6
+ with:
+ persist-credentials: false
+ fetch-depth: 0
+ path: vcpkg
+ repository: microsoft/vcpkg
+ - name: Bootstrap vcpkg
+ shell: pwsh
+ run: |
+ vcpkg\bootstrap-vcpkg.bat
+ $VCPKG_ROOT = $(Resolve-Path -LiteralPath "vcpkg").ToString()
+ Write-Output ${VCPKG_ROOT} | `
+ Out-File -FilePath ${Env:GITHUB_PATH} -Encoding utf8 -Append
+ Write-Output "VCPKG_ROOT=${VCPKG_ROOT}" | `
+ Out-File -FilePath ${Env:GITHUB_ENV} -Encoding utf8 -Append
+ - name: Setup NuGet credentials for vcpkg caching
+ shell: bash
+ run: |
+ $(vcpkg fetch nuget | tail -n 1) \
+ sources add \
+ -source
"https://nuget.pkg.github.com/$GITHUB_REPOSITORY_OWNER/index.json" \
+ -storepasswordincleartext \
+ -name "GitHub" \
+ -username "$GITHUB_REPOSITORY_OWNER" \
+ -password "${{ inputs.github-token }}"
+ $(vcpkg fetch nuget | tail -n 1) \
+ setapikey "${{ inputs.github-token }}" \
+ -source
"https://nuget.pkg.github.com/$GITHUB_REPOSITORY_OWNER/index.json"
+ - name: Build
+ shell: cmd
+ run: |
+ set VCPKG_ROOT_KEEP=%VCPKG_ROOT%
+ call "C:\Program Files\Microsoft Visual
Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64
+ set VCPKG_ROOT=%VCPKG_ROOT_KEEP%
+ bash -c "ci/scripts/cpp_build.sh $(pwd) $(pwd)/build"
+ - name: Register Flight SQL ODBC Driver
+ shell: cmd
+ run: |
+ call "cpp\src\arrow\flight\sql\odbc\tests\install_odbc.cmd" ${{
github.workspace }}\build\cpp\%ARROW_BUILD_TYPE%\arrow_flight_sql_odbc.dll
diff --git a/.github/workflows/cpp_extra.yml b/.github/workflows/cpp_extra.yml
index 5d13d36f83..e4e51608db 100644
--- a/.github/workflows/cpp_extra.yml
+++ b/.github/workflows/cpp_extra.yml
@@ -605,87 +605,16 @@ jobs:
VCPKG_DEFAULT_TRIPLET: amd64-windows-no-absl-sync-release
VCPKG_OVERLAY_TRIPLETS: ${{ github.workspace }}/ci/vcpkg
steps:
- - name: Disable Crash Dialogs
- run: |
- reg add `
- "HKCU\SOFTWARE\Microsoft\Windows\Windows Error Reporting" `
- /v DontShowUI `
- /t REG_DWORD `
- /d 1 `
- /f
- name: Checkout Arrow
uses: actions/checkout@v6
with:
persist-credentials: false
fetch-depth: 0
submodules: recursive
- - name: Download Timezone Database
- shell: bash
- run: ci/scripts/download_tz_database.sh
- - name: Install ccache
- shell: bash
- run: |
- ci/scripts/install_ccache.sh 4.12.1 /usr
- - name: Setup ccache
- shell: bash
- run: |
- ci/scripts/ccache_setup.sh
- - name: ccache info
- id: ccache-info
- shell: bash
- run: |
- echo "cache-dir=$(ccache --get-config cache_dir)" >> $GITHUB_OUTPUT
- - name: Restore ccache
- uses:
apache/infrastructure-actions/stash/restore@0ba14156c9f4c3cfbe4b0c9f36339ab0f8d81e53
+ - name: Build ODBC Windows
+ uses: ./.github/actions/odbc-windows
with:
- path: ${{ steps.ccache-info.outputs.cache-dir }}
- key: cpp-odbc-ccache-windows-x64
- - name: Checkout vcpkg
- uses: actions/checkout@v6
- with:
- persist-credentials: false
- fetch-depth: 0
- path: vcpkg
- repository: microsoft/vcpkg
- - name: Bootstrap vcpkg
- run: |
- vcpkg\bootstrap-vcpkg.bat
- $VCPKG_ROOT = $(Resolve-Path -LiteralPath "vcpkg").ToString()
- Write-Output ${VCPKG_ROOT} | `
- Out-File -FilePath ${Env:GITHUB_PATH} -Encoding utf8 -Append
- Write-Output "VCPKG_ROOT=${VCPKG_ROOT}" | `
- Out-File -FilePath ${Env:GITHUB_ENV} -Encoding utf8 -Append
- - name: Setup NuGet credentials for vcpkg caching
- shell: bash
- run: |
- $(vcpkg fetch nuget | tail -n 1) \
- sources add \
- -source
"https://nuget.pkg.github.com/$GITHUB_REPOSITORY_OWNER/index.json" \
- -storepasswordincleartext \
- -name "GitHub" \
- -username "$GITHUB_REPOSITORY_OWNER" \
- -password "${{ secrets.GITHUB_TOKEN }}"
- $(vcpkg fetch nuget | tail -n 1) \
- setapikey "${{ secrets.GITHUB_TOKEN }}" \
- -source
"https://nuget.pkg.github.com/$GITHUB_REPOSITORY_OWNER/index.json"
- - name: Build
- shell: cmd
- run: |
- set VCPKG_ROOT_KEEP=%VCPKG_ROOT%
- call "C:\Program Files\Microsoft Visual
Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64
- set VCPKG_ROOT=%VCPKG_ROOT_KEEP%
- bash -c "ci/scripts/cpp_build.sh $(pwd) $(pwd)/build"
- - name: Save ccache
- if: ${{ !cancelled() }}
- continue-on-error: true
- uses:
apache/infrastructure-actions/stash/save@0ba14156c9f4c3cfbe4b0c9f36339ab0f8d81e53
- with:
- path: ${{ steps.ccache-info.outputs.cache-dir }}
- key: cpp-odbc-ccache-windows-x64
- - name: Register Flight SQL ODBC Driver
- shell: cmd
- run: |
- call "cpp\src\arrow\flight\sql\odbc\tests\install_odbc.cmd" ${{
github.workspace }}\build\cpp\%ARROW_BUILD_TYPE%\arrow_flight_sql_odbc.dll
+ github-token: ${{ secrets.GITHUB_TOKEN }}
- name: Test
shell: cmd
run: |
@@ -708,7 +637,7 @@ jobs:
wix --version
cd build/cpp
cpack
- - name: Upload the artifacts to the job
+ - name: Upload ODBC MSI to the job
uses: actions/upload-artifact@v7
with:
name: flight-sql-odbc-msi-installer
@@ -797,40 +726,6 @@ jobs:
remote_key: ${{ secrets.NIGHTLIES_RSYNC_KEY }}
remote_host_key: ${{ secrets.NIGHTLIES_RSYNC_HOST_KEY }}
- odbc-release:
- needs: odbc-msvc
- name: ODBC release
- runs-on: ubuntu-latest
- if: ${{ startsWith(github.ref_name, 'apache-arrow-') &&
contains(github.ref_name, '-rc') }}
- permissions:
- # Upload to GitHub Release
- contents: write
- steps:
- - name: Checkout Arrow
- uses: actions/checkout@v6
- with:
- persist-credentials: false
- fetch-depth: 0
- submodules: recursive
- - name: Download the artifacts
- uses: actions/download-artifact@v8
- with:
- name: flight-sql-odbc-msi-installer
- - name: Wait for creating GitHub Release
- env:
- GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- run: |
- dev/release/utils-watch-gh-workflow.sh \
- ${GITHUB_REF_NAME} \
- release_candidate.yml
- - name: Upload the artifacts to GitHub Release
- env:
- GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- run: |
- gh release upload ${GITHUB_REF_NAME} \
- --clobber \
- Apache-Arrow-Flight-SQL-ODBC-*-win64.msi
-
report-extra-cpp:
if: github.event_name == 'schedule' && always()
needs:
diff --git a/.github/workflows/package_odbc.yml
b/.github/workflows/package_odbc.yml
new file mode 100644
index 0000000000..a735f25667
--- /dev/null
+++ b/.github/workflows/package_odbc.yml
@@ -0,0 +1,178 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+name: Package Apache Arrow Flight SQL ODBC Driver
+
+on:
+ push:
+ tags:
+ - "apache-arrow-*-rc*"
+ workflow_dispatch:
+ inputs:
+ odbc_release_step:
+ description: 'ODBC MSI release step'
+ required: false
+ default: false
+ type: boolean
+
+concurrency:
+ group: ${{ github.repository }}-${{ github.head_ref || github.sha }}-${{
github.workflow }}
+ cancel-in-progress: true
+
+permissions:
+ actions: read
+ contents: read
+ pull-requests: read
+
+jobs:
+ # GH-49537 CPack only packages from a single build directory, so the build
+ # cannot be reused and we need to rebuild the MSI in a separate workflow.
This
+ # means both the odbc-msvc-upload-dll and odbc-msvc-upload-msi jobs do a
full build.
+ odbc-msvc-upload-dll:
+ name: ODBC Windows Upload Unsigned DLL
+ runs-on: windows-2022
+ if: github.event_name == 'push'
+ timeout-minutes: 240
+ permissions:
+ packages: write
+ env: &odbc_msvc_env
+ ARROW_BUILD_SHARED: ON
+ ARROW_BUILD_STATIC: OFF
+ ARROW_BUILD_TESTS: OFF
+ ARROW_BUILD_TYPE: release
+ # Turn Arrow CSV off to disable `find_package(Arrow)` check on MSVC CI.
+ # GH-49050 TODO: enable `find_package(Arrow)` check on MSVC CI.
+ ARROW_CSV: OFF
+ ARROW_DEPENDENCY_SOURCE: VCPKG
+ ARROW_FLIGHT_SQL_ODBC: ON
+ ARROW_FLIGHT_SQL_ODBC_INSTALLER: ON
+ ARROW_HOME: /usr
+ CMAKE_GENERATOR: Ninja
+ CMAKE_INSTALL_PREFIX: /usr
+ VCPKG_BINARY_SOURCES: 'clear;nugettimeout,600;nuget,GitHub,readwrite'
+ VCPKG_DEFAULT_TRIPLET: x64-windows
+ steps:
+ - name: Checkout Arrow
+ uses: actions/checkout@v6
+ with:
+ persist-credentials: false
+ fetch-depth: 0
+ submodules: recursive
+ - name: Build ODBC Windows
+ uses: ./.github/actions/odbc-windows
+ with:
+ github-token: ${{ secrets.GITHUB_TOKEN }}
+ - name: Rename Unsigned ODBC DLL
+ run: |
+ Rename-Item `
+ -Path build/cpp/${{ env.ARROW_BUILD_TYPE
}}/arrow_flight_sql_odbc.dll `
+ -NewName arrow_flight_sql_odbc_unsigned.dll
+ - name: Upload ODBC DLL to the job
+ uses: actions/upload-artifact@v7
+ with:
+ name: flight-sql-odbc-dll
+ path: build/cpp/${{ env.ARROW_BUILD_TYPE
}}/arrow_flight_sql_odbc_unsigned.dll
+ if-no-files-found: error
+
+ odbc-dll-release:
+ needs: odbc-msvc-upload-dll
+ name: Upload Unsigned ODBC DLL to Release
+ runs-on: ubuntu-latest
+ permissions:
+ # Upload to GitHub Release
+ contents: write
+ steps:
+ - name: Checkout Arrow
+ uses: actions/checkout@v6
+ with:
+ persist-credentials: false
+ fetch-depth: 0
+ submodules: recursive
+ - name: Download the artifacts
+ uses: actions/download-artifact@v8
+ with:
+ name: flight-sql-odbc-dll
+ - name: Wait for creating GitHub Release
+ env:
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ run: |
+ dev/release/utils-watch-gh-workflow.sh \
+ ${GITHUB_REF_NAME} \
+ release_candidate.yml
+ - name: Upload the artifacts to GitHub Release
+ env:
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ run: |
+ gh release upload ${GITHUB_REF_NAME} \
+ --clobber \
+ arrow_flight_sql_odbc_unsigned.dll
+
+ odbc-msvc-upload-msi:
+ name: ODBC Windows Build & Upload Unsigned MSI
+ runs-on: windows-2022
+ if: inputs.odbc_release_step
+ timeout-minutes: 240
+ permissions:
+ # Upload to GitHub Release
+ contents: write
+ packages: write
+ env: *odbc_msvc_env
+ steps:
+ - name: Checkout Arrow
+ uses: actions/checkout@v6
+ with:
+ persist-credentials: false
+ fetch-depth: 0
+ submodules: recursive
+ - name: Download signed ODBC DLL
+ env:
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ run: |
+ gh release download $env:GITHUB_REF_NAME `
+ --pattern arrow_flight_sql_odbc.dll `
+ --clobber
+ - name: Build ODBC Windows
+ uses: ./.github/actions/odbc-windows
+ with:
+ github-token: ${{ secrets.GITHUB_TOKEN }}
+ - name: Replace unsigned DLL with signed DLL
+ run: |
+ Move-Item `
+ -Path ./arrow_flight_sql_odbc.dll `
+ -Destination build/cpp/${{ env.ARROW_BUILD_TYPE
}}/arrow_flight_sql_odbc.dll `
+ -Force
+ - name: Install WiX Toolset
+ shell: pwsh
+ run: |
+ Invoke-WebRequest -Uri
https://github.com/wixtoolset/wix/releases/download/v6.0.0/wix-cli-x64.msi
-OutFile wix-cli-x64.msi
+ Start-Process -FilePath wix-cli-x64.msi -ArgumentList '/quiet',
'Include_freethreaded=1' -Wait
+ echo "C:\Program Files\WiX Toolset v6.0\bin\" | Out-File -FilePath
$env:GITHUB_PATH -Encoding utf8 -Append
+ - name: Build MSI ODBC installer
+ shell: pwsh
+ run: |
+ # Verify WiX version
+ wix --version
+ cd build/cpp
+ cpack
+ - name: Upload the artifacts to GitHub Release
+ env:
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ run: |
+ cd build/cpp
+ gh release upload $env:GITHUB_REF_NAME `
+ --clobber `
+ Apache-Arrow-Flight-SQL-ODBC-*-win64.msi
diff --git a/dev/release/07-flightsqlodbc-upload.sh
b/dev/release/07-flightsqlodbc-upload.sh
index c47b5076f9..c823bc84ae 100755
--- a/dev/release/07-flightsqlodbc-upload.sh
+++ b/dev/release/07-flightsqlodbc-upload.sh
@@ -102,7 +102,7 @@ if [ -e "${tmp_dir}" ]; then
fi
if [ "${PHASE_SIGN_DLL}" -gt 0 ]; then
- echo "[1/8 Downloading ${dll_unsigned} from release..."
+ echo "[1/8] Downloading ${dll_unsigned} from release..."
gh release download "${tag}" \
--repo "${GITHUB_REPOSITORY}" \
--pattern "${dll_unsigned}" \
@@ -112,7 +112,7 @@ if [ "${PHASE_SIGN_DLL}" -gt 0 ]; then
exit 1
fi
- echo "[2/8 Signing ${dll_unsigned}..."
+ echo "[2/8] Signing ${dll_unsigned}..."
echo "NOTE: Running jsign. You may be prompted for your OTP PIN..."
jsign --storetype ESIGNER \
--alias d97c5110-c66a-4c0c-ac0c-1cd6af812ee6 \
@@ -128,7 +128,7 @@ if [ "${PHASE_SIGN_DLL}" -gt 0 ]; then
exit 1
fi
- echo "[3/8 Uploading signed DLL to GitHub Release..."
+ echo "[3/8] Uploading signed DLL to GitHub Release..."
gh release upload "${tag}" \
--repo "${GITHUB_REPOSITORY}" \
--clobber \
@@ -136,19 +136,19 @@ if [ "${PHASE_SIGN_DLL}" -gt 0 ]; then
fi
if [ "${PHASE_BUILD_MSI}" -gt 0 ]; then
- echo "[4/8 Triggering odbc_release_step in cpp_extra.yml workflow..."
- gh workflow run cpp_extra.yml \
+ echo "[4/8] Triggering odbc_release_step in package_odbc.yml workflow..."
+ gh workflow run package_odbc.yml \
--repo "${GITHUB_REPOSITORY}" \
--ref "${tag}" \
--field odbc_release_step=true
- echo "[5/8 Waiting for workflow to complete. This can take a very long
time..."
+ echo "[5/8] Waiting for workflow to complete. This can take a very long
time..."
REPOSITORY="${GITHUB_REPOSITORY}" \
- "${SOURCE_DIR}/utils-watch-gh-workflow.sh" "${tag}" cpp_extra.yml
+ "${SOURCE_DIR}/utils-watch-gh-workflow.sh" "${tag}" package_odbc.yml
fi
if [ "${PHASE_SIGN_MSI}" -gt 0 ]; then
- echo "[6/8 Downloading unsigned MSI..."
+ echo "[6/8] Downloading unsigned MSI..."
gh release download "${tag}" \
--repo "${GITHUB_REPOSITORY}" \
--pattern "Apache-Arrow-Flight-SQL-ODBC-${version}-win64.msi" \
@@ -159,7 +159,7 @@ if [ "${PHASE_SIGN_MSI}" -gt 0 ]; then
exit 1
fi
- echo "[7/8 Signing MSI..."
+ echo "[7/8] Signing MSI..."
echo "NOTE: Running jsign. You may be prompted for your OTP PIN..."
jsign --storetype ESIGNER \
--alias d97c5110-c66a-4c0c-ac0c-1cd6af812ee6 \
@@ -174,7 +174,7 @@ if [ "${PHASE_SIGN_MSI}" -gt 0 ]; then
exit 1
fi
- echo "[8/8 Uploading signed MSI to GitHub Release..."
+ echo "[8/8] Uploading signed MSI to GitHub Release..."
gh release upload "${tag}" \
--repo "${GITHUB_REPOSITORY}" \
--clobber \