Skip to content

Commit c153fd8

Browse files
committed
add step to generate a windows msi installer of the Arduino CLI
1 parent 9c784d8 commit c153fd8

File tree

5 files changed

+273
-2
lines changed

5 files changed

+273
-2
lines changed

.github/workflows/publish-go-nightly-task.yml

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,9 +162,65 @@ jobs:
162162
name: ${{ env.ARTIFACT_NAME }}
163163
path: ${{ env.DIST_DIR }}/${{ env.PACKAGE_FILENAME }}
164164

165+
create-windows-installer:
166+
runs-on: windows-latest
167+
needs: create-nightly-artifacts
168+
169+
defaults:
170+
run:
171+
shell: bash
172+
173+
env:
174+
INSTALLER_CERT_WINDOWS_PFX: "/tmp/cert.pfx"
175+
SIGNTOOL_PATH: "C:/Program Files (x86)/Windows Kits/10/bin/10.0.17763.0/x86/signtool.exe"
176+
177+
steps:
178+
- name: Checkout repository
179+
uses: actions/checkout@v3
180+
181+
- name: Download artifacts
182+
uses: actions/download-artifact@v3
183+
with:
184+
name: ${{ env.ARTIFACT_NAME }}
185+
path: ${{ env.DIST_DIR }}
186+
187+
- name: Prepare PATH
188+
id: setupmsbuild
189+
uses: microsoft/setup-msbuild@v1
190+
191+
- name: Build MSI
192+
id: buildmsi
193+
env:
194+
MSBUILD_PATH: ${{ steps.setupmsbuild.outputs.msbuildPath }}
195+
run: |
196+
TAG="$(date -u +"%Y%m%d")"
197+
WIX_TAG="0.0.$TAG" # use something like 0.0.20220930 as version for the installer since wix is not happy with it, this only affects nightly builds (error CNDL0108)
198+
PACKAGE_FILENAME="${{ env.PROJECT_NAME }}_${TAG}_Windows_64bit"
199+
SOURCE_DIR="${GITHUB_WORKSPACE}/${{ env.DIST_DIR }}/${{ env.PROJECT_NAME }}_windows_amd64/"
200+
"${{ env.MSBUILD_PATH }}\MSBuild.exe" ./installer/cli.wixproj -p:SourceDir="$SOURCE_DIR" -p:OutputPath="${GITHUB_WORKSPACE}/${{ env.DIST_DIR }}" -p:OutputName="$PACKAGE_FILENAME" -p:ProductVersion="$WIX_TAG"
201+
202+
- name: Save Win signing certificate to file
203+
run: echo "${{ secrets.INSTALLER_CERT_WINDOWS_PFX }}" | base64 --decode > ${{ env.INSTALLER_CERT_WINDOWS_PFX}}
204+
205+
- name: Sign MSI
206+
env:
207+
MSI_FILE: ${{ steps.buildmsi.outputs.msi }} # this comes from .installer/cli.wixproj
208+
CERT_PASSWORD: ${{ secrets.INSTALLER_CERT_WINDOWS_PASSWORD }}
209+
run: |
210+
"${{ env.SIGNTOOL_PATH }}" sign -d "Arduino CLI" -f ${{ env.INSTALLER_CERT_WINDOWS_PFX}} -p ${{ env.CERT_PASSWORD }} -fd sha256 -tr http://timestamp.digicert.com -v "${{ env.MSI_FILE }}"
211+
212+
- name: Upload artifacts
213+
uses: actions/upload-artifact@v3
214+
env:
215+
MSI_FILE: ${{ steps.buildmsi.outputs.msi }}
216+
with:
217+
if-no-files-found: error
218+
name: ${{ env.ARTIFACT_NAME }}
219+
path: ${{ env.MSI_FILE }}
220+
165221
publish-nightly:
166222
runs-on: ubuntu-latest
167-
needs: notarize-macos
223+
needs: [notarize-macos, create-windows-installer]
168224

169225
steps:
170226
- name: Download artifact

.github/workflows/release-go-task.yml

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,9 +169,64 @@ jobs:
169169
name: ${{ env.ARTIFACT_NAME }}
170170
path: ${{ env.DIST_DIR }}/${{ env.PACKAGE_FILENAME }}
171171

172+
create-windows-installer:
173+
runs-on: windows-latest
174+
needs: create-release-artifacts
175+
176+
defaults:
177+
run:
178+
shell: bash
179+
180+
env:
181+
INSTALLER_CERT_WINDOWS_PFX: "/tmp/cert.pfx"
182+
SIGNTOOL_PATH: "C:/Program Files (x86)/Windows Kits/10/bin/10.0.17763.0/x86/signtool.exe"
183+
184+
steps:
185+
- name: Checkout repository
186+
uses: actions/checkout@v3
187+
188+
- name: Download artifacts
189+
uses: actions/download-artifact@v3
190+
with:
191+
name: ${{ env.ARTIFACT_NAME }}
192+
path: ${{ env.DIST_DIR }}
193+
194+
- name: Prepare PATH
195+
id: setupmsbuild
196+
uses: microsoft/setup-msbuild@v1
197+
198+
- name: Build MSI
199+
id: buildmsi
200+
env:
201+
MSBUILD_PATH: ${{ steps.setupmsbuild.outputs.msbuildPath }}
202+
run: |
203+
TAG="${GITHUB_REF/refs\/tags\//}"
204+
PACKAGE_FILENAME="${{ env.PROJECT_NAME }}_${TAG}_Windows_64bit"
205+
SOURCE_DIR="${{ env.DIST_DIR }}/${{ env.PROJECT_NAME }}_windows_amd64/${{ env.PROJECT_NAME }}.exe"
206+
"${{ env.MSBUILD_PATH }}\MSBuild.exe" ./installer/cli.wixproj -p:SourceDir="$SOURCE_DIR" -p:OutputPath="${{ env.DIST_DIR }}" -p:OutputName="$PACKAGE_FILENAME" -p:ProductVersion="$TAG"
207+
208+
- name: Save Win signing certificate to file
209+
run: echo "${{ secrets.INSTALLER_CERT_WINDOWS_PFX }}" | base64 --decode > ${{ env.INSTALLER_CERT_WINDOWS_PFX}}
210+
211+
- name: Sign MSI
212+
env:
213+
MSI_FILE: ${{ steps.buildmsi.outputs.msi }} # this comes from .installer/cli.wixproj
214+
CERT_PASSWORD: ${{ secrets.INSTALLER_CERT_WINDOWS_PASSWORD }}
215+
run: |
216+
"${{ env.SIGNTOOL_PATH }}" sign -d "Arduino CLI" -f ${{ env.INSTALLER_CERT_WINDOWS_PFX}} -p ${{ env.CERT_PASSWORD }} -fd sha256 -tr http://timestamp.digicert.com -v "${{ env.MSI_FILE }}"
217+
218+
- name: Upload artifacts
219+
uses: actions/upload-artifact@v3
220+
env:
221+
MSI_FILE: ${{ steps.buildmsi.outputs.msi }}
222+
with:
223+
if-no-files-found: error
224+
name: ${{ env.ARTIFACT_NAME }}
225+
path: ${{ env.MSI_FILE }}
226+
172227
create-release:
173228
runs-on: ubuntu-latest
174-
needs: notarize-macos
229+
needs: [notarize-macos, create-windows-installer]
175230

176231
steps:
177232
- name: Download artifact

installer/cli.wixproj

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3+
<PropertyGroup>
4+
<Configuration>Release</Configuration>
5+
<Platform Condition="'$(Platform)' == ''">x64</Platform>
6+
<!-- "ProductVersion" gets overridden when run with the commandline by the relese CI, this is usefull to define it if not defined -->
7+
<ProductVersion Condition="'$(ProductVersion)' == ''">0.1.0</ProductVersion>
8+
<!-- "OutputName" gets overridden when run with the commandline by the release CI, it's the name of the output file -->
9+
<OutputName Condition="'$(OutputName)' == ''">$(MSBuildProjectName)</OutputName>
10+
<OutputType>package</OutputType>
11+
<!-- "OutputName" is set when run with the commandline by the release CI, it's the path of the output file -->
12+
<DefineConstants>
13+
$(DefineConstants);
14+
ProductVersion=$(ProductVersion);
15+
</DefineConstants>
16+
<WixTargetsPath Condition="'$(WixTargetsPath)' == ''">$(MSBuildExtensionsPath)\Microsoft\WiX\v3.x\Wix.targets</WixTargetsPath>
17+
</PropertyGroup>
18+
<ItemGroup>
19+
<!-- path and name of the additional files that contains additional config for the installer generation and needs Compile -->
20+
<Compile Include="cli.wxs"/>
21+
<Compile Include="ui.wxs"/>
22+
</ItemGroup>
23+
<ItemGroup>
24+
<!-- Include directories containing both user-specified output and unzipped release for ease -->
25+
<!-- "SourceDir" is defined when run with the commandline by the release CI, it's the folder containing files to include in the installer -->
26+
<BindInputPaths Include="$(SourceDir)"/>
27+
</ItemGroup>
28+
<ItemGroup>
29+
<!-- https://wixtoolset.org//documentation/manual/v3/wixui/wixui_dialog_library.html -->
30+
<WixExtension Include="WixUIExtension"/>
31+
<!-- we need the following to be able to broadcast the environment vars change -->
32+
<WixExtension Include="WixUtilExtension"/>
33+
</ItemGroup>
34+
<Target Name="SetStepOutput" AfterTargets="Build" Condition="'$(GITHUB_ACTIONS)' != ''">
35+
<!-- Make sure the correct target path is always set as the step output -->
36+
<Message Importance="high" Text="::set-output name=msi::$(TargetPath)"/>
37+
</Target>
38+
<Import Project="$(WixTargetsPath)"/>
39+
</Project>

installer/cli.wxs

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
3+
<?ifndef ProductVersion?>
4+
<?error ProductVersion property not defined?>
5+
<?endif?>
6+
7+
<?define UpgradeCode = "96AEA20C-2FB2-431D-87A4-D7A6E57F70B7"?>
8+
9+
<!-- Define a unique UpgradeCode per platform -->
10+
<?if $(var.Platform) = "x64"?>
11+
<?define ProgramFilesFolder = "ProgramFiles64Folder"?>
12+
<?elseif $(var.Platform) = "x86"?>
13+
<?define ProgramFilesFolder = "ProgramFilesFolder"?>
14+
<?endif?>
15+
16+
<!-- https://www.add-in-express.com/docs/wix-setup-package.php -->
17+
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
18+
<!-- https://wixtoolset.org/documentation/manual/v3/xsd/wix/product.html -->
19+
<Product Id="*" Name="Arduino CLI" Version="$(var.ProductVersion)" Language="1033" Manufacturer="Arduino Srl." UpgradeCode="$(var.UpgradeCode)">
20+
<!-- https://wixtoolset.org/documentation/manual/v3/xsd/wix/package.html -->
21+
<Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine"/>
22+
<!-- by adding this attribute, you create a single .MSI file as opposed to getting a CAB file along with the .MSI. -->
23+
<MediaTemplate EmbedCab="yes"/>
24+
25+
<!-- Remove older product(s) early but within the transaction -->
26+
<MajorUpgrade DowngradeErrorMessage="A newer version of !(bind.property.ProductName) is already installed."/>
27+
28+
<!-- directory structure to create -->
29+
<!-- https://wixtoolset.org/documentation/manual/v3/howtos/files_and_registry/add_a_file.html -->
30+
<!-- Outermost folder (kind of virtual). Fixed entry. -->
31+
<Directory Id="TARGETDIR" Name="SourceDir">
32+
<!-- "ProgramFilesFolder" is a variable containing the absolute path. -->
33+
<!-- For a list of folder variables, see: http://msdn.microsoft.com/en-us/library/aa372057%28VS.85%29.aspx -->
34+
<Directory Id="$(var.ProgramFilesFolder)" Name="Program Files">
35+
<!-- All folders from here on are relative to their parent. -->
36+
<!-- INSTALLDIR is a property name. We need it later for the UI (to be able to change the install dir. -->
37+
<Directory Id="INSTALLDIR" Name="Arduino CLI"/>
38+
</Directory>
39+
</Directory>
40+
41+
<!-- Determine the directory of a previous installation (if one exists). If not INSTALLDIR stays empty -->
42+
<Property Id="INSTALLDIR">
43+
<RegistrySearch Id="InstallDir" Root="HKLM" Key="SOFTWARE\Arduino\CLI" Name="InstallDir" Type="directory"/>
44+
</Property>
45+
46+
<!-- Features define which parts of the application can be installed in a custom installation -->
47+
<Feature Id="DefaultFeature" ConfigurableDirectory="INSTALLDIR">
48+
<Component Directory="INSTALLDIR">
49+
<File Name="arduino-cli.exe"/>
50+
<Environment Id="Path" Action="set" Name="PATH" Part="last" System="yes" Value="[INSTALLDIR]"/>
51+
</Component>
52+
53+
<!-- Persist the INSTALLDIR and restore it in subsequent installs -->
54+
<Component Directory="INSTALLDIR">
55+
<RegistryValue Root="HKLM" Key="SOFTWARE\Arduino\CLI" Name="InstallDir" Type="string" Value="[INSTALLDIR]"/>
56+
</Component>
57+
</Feature>
58+
59+
<!-- Broadcast environment variable changes -->
60+
<!-- https://wixtoolset.org/documentation/manual/v3/customactions/wixsettingchange.html -->
61+
<CustomActionRef Id="WixBroadcastEnvironmentChange" />
62+
63+
<!-- Use customized WixUI_InstallDir that removes WixUI_LicenseAgreementDlg -->
64+
<Property Id="WIXUI_INSTALLDIR" Value="INSTALLDIR"/>
65+
<UIRef Id="ArduinoCLI_InstallDir"/>
66+
</Product>
67+
</Wix>

installer/ui.wxs

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
3+
<Fragment>
4+
<UI Id="ArduinoCLI_InstallDir">
5+
<TextStyle Id="WixUI_Font_Normal" FaceName="Tahoma" Size="8" />
6+
<TextStyle Id="WixUI_Font_Bigger" FaceName="Tahoma" Size="12" />
7+
<TextStyle Id="WixUI_Font_Title" FaceName="Tahoma" Size="9" Bold="yes" />
8+
9+
<Property Id="DefaultUIFont" Value="WixUI_Font_Normal" />
10+
<Property Id="WixUI_Mode" Value="InstallDir" />
11+
12+
<DialogRef Id="BrowseDlg" />
13+
<DialogRef Id="DiskCostDlg" />
14+
<DialogRef Id="ErrorDlg" />
15+
<DialogRef Id="FatalError" />
16+
<DialogRef Id="FilesInUse" />
17+
<DialogRef Id="MsiRMFilesInUse" />
18+
<DialogRef Id="PrepareDlg" />
19+
<DialogRef Id="ProgressDlg" />
20+
<DialogRef Id="ResumeDlg" />
21+
<DialogRef Id="UserExit" />
22+
23+
<Publish Dialog="BrowseDlg" Control="OK" Event="DoAction" Value="WixUIValidatePath" Order="3">1</Publish>
24+
<Publish Dialog="BrowseDlg" Control="OK" Event="SpawnDialog" Value="InvalidDirDlg" Order="4"><![CDATA[NOT WIXUI_DONTVALIDATEPATH AND WIXUI_INSTALLDIR_VALID<>"1"]]></Publish>
25+
26+
<Publish Dialog="ExitDialog" Control="Finish" Event="EndDialog" Value="Return" Order="999">1</Publish>
27+
28+
<Publish Dialog="WelcomeDlg" Control="Next" Event="NewDialog" Value="InstallDirDlg">NOT Installed</Publish>
29+
<Publish Dialog="WelcomeDlg" Control="Next" Event="NewDialog" Value="VerifyReadyDlg">Installed AND PATCH</Publish>
30+
31+
<Publish Dialog="InstallDirDlg" Control="Back" Event="NewDialog" Value="WelcomeDlg">1</Publish>
32+
<Publish Dialog="InstallDirDlg" Control="Next" Event="SetTargetPath" Value="[WIXUI_INSTALLDIR]" Order="1">1</Publish>
33+
<Publish Dialog="InstallDirDlg" Control="Next" Event="DoAction" Value="WixUIValidatePath" Order="2">NOT WIXUI_DONTVALIDATEPATH</Publish>
34+
<Publish Dialog="InstallDirDlg" Control="Next" Event="SpawnDialog" Value="InvalidDirDlg" Order="3"><![CDATA[NOT WIXUI_DONTVALIDATEPATH AND WIXUI_INSTALLDIR_VALID<>"1"]]></Publish>
35+
<Publish Dialog="InstallDirDlg" Control="Next" Event="NewDialog" Value="VerifyReadyDlg" Order="4">WIXUI_DONTVALIDATEPATH OR WIXUI_INSTALLDIR_VALID="1"</Publish>
36+
<Publish Dialog="InstallDirDlg" Control="ChangeFolder" Property="_BrowseProperty" Value="[WIXUI_INSTALLDIR]" Order="1">1</Publish>
37+
<Publish Dialog="InstallDirDlg" Control="ChangeFolder" Event="SpawnDialog" Value="BrowseDlg" Order="2">1</Publish>
38+
39+
<Publish Dialog="VerifyReadyDlg" Control="Back" Event="NewDialog" Value="InstallDirDlg" Order="1">NOT Installed</Publish>
40+
<Publish Dialog="VerifyReadyDlg" Control="Back" Event="NewDialog" Value="MaintenanceTypeDlg" Order="2">Installed AND NOT PATCH</Publish>
41+
<Publish Dialog="VerifyReadyDlg" Control="Back" Event="NewDialog" Value="WelcomeDlg" Order="2">Installed AND PATCH</Publish>
42+
43+
<Publish Dialog="MaintenanceWelcomeDlg" Control="Next" Event="NewDialog" Value="MaintenanceTypeDlg">1</Publish>
44+
45+
<Publish Dialog="MaintenanceTypeDlg" Control="RepairButton" Event="NewDialog" Value="VerifyReadyDlg">1</Publish>
46+
<Publish Dialog="MaintenanceTypeDlg" Control="RemoveButton" Event="NewDialog" Value="VerifyReadyDlg">1</Publish>
47+
<Publish Dialog="MaintenanceTypeDlg" Control="Back" Event="NewDialog" Value="MaintenanceWelcomeDlg">1</Publish>
48+
49+
<Property Id="ARPNOMODIFY" Value="1" />
50+
</UI>
51+
52+
<UIRef Id="WixUI_Common" />
53+
</Fragment>
54+
</Wix>

0 commit comments

Comments
 (0)