Skip to content

Add windows .msi installer to the CI #1899

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 18 commits into from
Oct 17, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/workflows/check-certificates.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ jobs:
- identifier: macOS signing certificate # Text used to identify certificate in notifications.
certificate-secret: INSTALLER_CERT_MAC_P12 # Name of the secret that contains the certificate.
password-secret: INSTALLER_CERT_MAC_PASSWORD # Name of the secret that contains the certificate password.
- identifier: Windows signing certificate
certificate-secret: INSTALLER_CERT_WINDOWS_PASSWORD
password-secret: INSTALLER_CERT_WINDOWS_PFX

steps:
- name: Set certificate path environment variable
Expand Down
81 changes: 72 additions & 9 deletions .github/workflows/publish-go-nightly-task.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ on:

jobs:
create-nightly-artifacts:
outputs:
version: ${{ steps.get-version.outputs.version }}
runs-on: ubuntu-latest

strategy:
Expand Down Expand Up @@ -50,6 +52,12 @@ jobs:
NIGHTLY: true
run: task dist:${{ matrix.os }}

- name: Output Version
id: get-version
env:
NIGHTLY: true
run: echo "::set-output name=version::$(task general:get-version)"

- name: Upload artifacts
uses: actions/upload-artifact@v3
with:
Expand All @@ -61,9 +69,6 @@ jobs:
name: Notarize ${{ matrix.artifact.name }}
runs-on: macos-latest
needs: create-nightly-artifacts
outputs:
checksum-darwin_amd64: ${{ steps.re-package.outputs.checksum-darwin_amd64 }}
checksum-darwin_arm64: ${{ steps.re-package.outputs.checksum-darwin_arm64 }}

env:
GON_CONFIG_PATH: gon.config.hcl
Expand Down Expand Up @@ -141,15 +146,14 @@ jobs:
gon "${{ env.GON_CONFIG_PATH }}"

- name: Re-package binary
id: re-package
working-directory: ${{ env.DIST_DIR }}
# Repackage the signed binary replaced in place by Gon (ignoring the output zip file)
run: |
# GitHub's upload/download-artifact@v2 actions don't preserve file permissions,
# so we need to add execution permission back until the action is made to do this.
chmod +x "${{ env.PROJECT_NAME }}_osx_${{ matrix.artifact.name }}/${{ env.PROJECT_NAME }}"
# Use of an array here is required for globbing
PACKAGE_FILENAME=(${{ env.PROJECT_NAME }}_nightly-*${{ matrix.artifact.path }})
VERSION=${{ needs.create-nightly-artifacts.outputs.version }}
PACKAGE_FILENAME=(${{ env.PROJECT_NAME }}_${VERSION}_${{ matrix.artifact.path }})
tar -czvf "$PACKAGE_FILENAME" \
-C "${{ env.PROJECT_NAME }}_osx_${{ matrix.artifact.name }}/" "${{ env.PROJECT_NAME }}" \
-C ../../ LICENSE.txt
Expand All @@ -162,9 +166,68 @@ jobs:
name: ${{ env.ARTIFACT_NAME }}
path: ${{ env.DIST_DIR }}/${{ env.PACKAGE_FILENAME }}

create-windows-installer:
runs-on: windows-latest
needs: create-nightly-artifacts

defaults:
run:
shell: bash

env:
INSTALLER_CERT_WINDOWS_PFX: "/tmp/cert.pfx"
# We are hardcoding the path for signtool because is not present on the windows PATH env var by default.
# Keep in mind that this path could change when upgrading to a new runner version
# https://github.com/actions/runner-images/blob/main/images/win/Windows2022-Readme.md#installed-windows-sdks
SIGNTOOL_PATH: "C:/Program Files (x86)/Windows Kits/10/bin/10.0.22621.0/x86/signtool.exe"

steps:
- name: Checkout repository
uses: actions/checkout@v3

- name: Download artifacts
uses: actions/download-artifact@v3
with:
name: ${{ env.ARTIFACT_NAME }}
path: ${{ env.DIST_DIR }}

- name: Prepare PATH
uses: microsoft/setup-msbuild@v1

- name: Build MSI
id: buildmsi
run: |
VERSION=${{ needs.create-nightly-artifacts.outputs.version }}
WIX_VERSION="0.0.0" # use 0.0.0 as version for the installer since wix is picky about other alternatives, this only affects nightly builds (error CNDL0242)
PACKAGE_FILENAME="${{ env.PROJECT_NAME }}_${VERSION}_Windows_64bit"
SOURCE_DIR="${GITHUB_WORKSPACE}/${{ env.DIST_DIR }}/${{ env.PROJECT_NAME }}_windows_amd64/"
MSBuild.exe ./installer/cli.wixproj -p:SourceDir="$SOURCE_DIR" -p:OutputPath="${GITHUB_WORKSPACE}/${{ env.DIST_DIR }}" -p:OutputName="$PACKAGE_FILENAME" -p:ProductVersion="$WIX_VERSION"

- name: Save Win signing certificate to file
run: echo "${{ secrets.INSTALLER_CERT_WINDOWS_PFX }}" | base64 --decode > ${{ env.INSTALLER_CERT_WINDOWS_PFX}}

- name: Sign MSI
env:
MSI_FILE: ${{ steps.buildmsi.outputs.msi }} # this comes from .installer/cli.wixproj
CERT_PASSWORD: ${{ secrets.INSTALLER_CERT_WINDOWS_PASSWORD }}
run: |
"${{ env.SIGNTOOL_PATH }}" sign -d "Arduino CLI" -f ${{ env.INSTALLER_CERT_WINDOWS_PFX}} -p ${{ env.CERT_PASSWORD }} -fd sha256 -tr http://timestamp.digicert.com -td SHA256 -v "${{ env.MSI_FILE }}"

- name: Upload artifacts
uses: actions/upload-artifact@v3
env:
MSI_FILE: ${{ steps.buildmsi.outputs.msi }}
with:
if-no-files-found: error
name: ${{ env.ARTIFACT_NAME }}
path: ${{ env.MSI_FILE }}

publish-nightly:
runs-on: ubuntu-latest
needs: notarize-macos
needs:
- create-nightly-artifacts
- notarize-macos
- create-windows-installer

steps:
- name: Download artifact
Expand All @@ -176,8 +239,8 @@ jobs:
- name: Create checksum file
working-directory: ${{ env.DIST_DIR}}
run: |
TAG="nightly-$(date -u +"%Y%m%d")"
sha256sum ${{ env.PROJECT_NAME }}_${TAG}* > ${TAG}-checksums.txt
VERSION=${{ needs.create-nightly-artifacts.outputs.version }}
sha256sum ${{ env.PROJECT_NAME }}_${VERSION}* > ${VERSION}-checksums.txt

- name: Upload release files on Arduino downloads servers
uses: docker://plugins/s3
Expand Down
77 changes: 69 additions & 8 deletions .github/workflows/release-go-task.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ on:

jobs:
create-release-artifacts:
outputs:
version: ${{ steps.get-version.outputs.version }}
runs-on: ubuntu-latest

strategy:
Expand Down Expand Up @@ -57,6 +59,10 @@ jobs:
- name: Build
run: task dist:${{ matrix.os }}

- name: Output Version
id: get-version
run: echo "::set-output name=version::$(task general:get-version)"

- name: Upload artifacts
uses: actions/upload-artifact@v3
with:
Expand All @@ -68,9 +74,6 @@ jobs:
name: Notarize ${{ matrix.artifact.name }}
runs-on: macos-latest
needs: create-release-artifacts
outputs:
checksum-darwin_amd64: ${{ steps.re-package.outputs.checksum-darwin_amd64 }}
checksum-darwin_arm64: ${{ steps.re-package.outputs.checksum-darwin_arm64 }}

env:
GON_CONFIG_PATH: gon.config.hcl
Expand Down Expand Up @@ -148,14 +151,13 @@ jobs:
gon "${{ env.GON_CONFIG_PATH }}"

- name: Re-package binary
id: re-package
working-directory: ${{ env.DIST_DIR }}
# Repackage the signed binary replaced in place by Gon (ignoring the output zip file)
run: |
# GitHub's upload/download-artifact@v2 actions don't preserve file permissions,
# so we need to add execution permission back until the action is made to do this.
chmod +x "${{ env.PROJECT_NAME }}_osx_${{ matrix.artifact.name }}/${{ env.PROJECT_NAME }}"
TAG="${GITHUB_REF/refs\/tags\//}"
TAG=${{ needs.create-release-artifacts.outputs.version }}
PACKAGE_FILENAME="${{ env.PROJECT_NAME }}_${TAG}_${{ matrix.artifact.path }}"
tar -czvf "$PACKAGE_FILENAME" \
-C "${{ env.PROJECT_NAME }}_osx_${{ matrix.artifact.name }}/" "${{ env.PROJECT_NAME }}" \
Expand All @@ -169,9 +171,68 @@ jobs:
name: ${{ env.ARTIFACT_NAME }}
path: ${{ env.DIST_DIR }}/${{ env.PACKAGE_FILENAME }}

create-windows-installer:
runs-on: windows-latest
needs: create-release-artifacts

defaults:
run:
shell: bash

env:
INSTALLER_CERT_WINDOWS_PFX: "/tmp/cert.pfx"
# We are hardcoding the path for signtool because is not present on the windows PATH env var by default.
# Keep in mind that this path could change when upgrading to a new runner version
# https://github.com/actions/runner-images/blob/main/images/win/Windows2022-Readme.md#installed-windows-sdks
SIGNTOOL_PATH: "C:/Program Files (x86)/Windows Kits/10/bin/10.0.22621.0/x86/signtool.exe"

steps:
- name: Checkout repository
uses: actions/checkout@v3

- name: Download artifacts
uses: actions/download-artifact@v3
with:
name: ${{ env.ARTIFACT_NAME }}
path: ${{ env.DIST_DIR }}

- name: Prepare PATH
uses: microsoft/setup-msbuild@v1

- name: Build MSI
id: buildmsi
run: |
TAG=${{ needs.create-release-artifacts.outputs.version }}
WIX_TAG="${TAG%%-*}" # removes "-rc*" since wix is not happy with it, this only affects RCs builds (error CNDL0108)
PACKAGE_FILENAME="${{ env.PROJECT_NAME }}_${TAG}_Windows_64bit"
SOURCE_DIR="${GITHUB_WORKSPACE}/${{ env.DIST_DIR }}/${{ env.PROJECT_NAME }}_windows_amd64/"
MSBuild.exe ./installer/cli.wixproj -p:SourceDir="$SOURCE_DIR" -p:OutputPath="${GITHUB_WORKSPACE}/${{ env.DIST_DIR }}" -p:OutputName="$PACKAGE_FILENAME" -p:ProductVersion="$WIX_TAG"

- name: Save Win signing certificate to file
run: echo "${{ secrets.INSTALLER_CERT_WINDOWS_PFX }}" | base64 --decode > ${{ env.INSTALLER_CERT_WINDOWS_PFX}}

- name: Sign MSI
env:
MSI_FILE: ${{ steps.buildmsi.outputs.msi }} # this comes from .installer/cli.wixproj
CERT_PASSWORD: ${{ secrets.INSTALLER_CERT_WINDOWS_PASSWORD }}
run: |
"${{ env.SIGNTOOL_PATH }}" sign -d "Arduino CLI" -f ${{ env.INSTALLER_CERT_WINDOWS_PFX}} -p ${{ env.CERT_PASSWORD }} -fd sha256 -tr http://timestamp.digicert.com -td SHA256 -v "${{ env.MSI_FILE }}"

- name: Upload artifacts
uses: actions/upload-artifact@v3
env:
MSI_FILE: ${{ steps.buildmsi.outputs.msi }}
with:
if-no-files-found: error
name: ${{ env.ARTIFACT_NAME }}
path: ${{ env.MSI_FILE }}

create-release:
runs-on: ubuntu-latest
needs: notarize-macos
needs:
- create-release-artifacts
- notarize-macos
- create-windows-installer

steps:
- name: Download artifact
Expand All @@ -183,7 +244,7 @@ jobs:
- name: Create checksum file
working-directory: ${{ env.DIST_DIR}}
run: |
TAG="${GITHUB_REF/refs\/tags\//}"
TAG=${{ needs.create-release-artifacts.outputs.version }}
sha256sum ${{ env.PROJECT_NAME }}_${TAG}* > ${TAG}-checksums.txt

- name: Identify Prerelease
Expand All @@ -193,7 +254,7 @@ jobs:
run: |
wget -q -P /tmp https://github.com/fsaintjacques/semver-tool/archive/3.0.0.zip
unzip -p /tmp/3.0.0.zip semver-tool-3.0.0/src/semver >/tmp/semver && chmod +x /tmp/semver
if [[ "$(/tmp/semver get prerel "${GITHUB_REF/refs\/tags\//}")" ]]; then echo "::set-output name=IS_PRE::true"; fi
if [[ "$(/tmp/semver get prerel ${{ needs.create-release-artifacts.outputs.version }} )" ]]; then echo "::set-output name=IS_PRE::true"; fi

- name: Create Github Release and upload artifacts
uses: ncipollo/release-action@v1
Expand Down
1 change: 1 addition & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@
/arduino/security/testdata/
/.licenses/
/site/
/installer/
5 changes: 5 additions & 0 deletions Taskfile.yml
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,11 @@ tasks:
cmds:
- poetry run mkdocs serve

general:get-version:
desc: Returns the version used in the project
cmds:
- echo {{.VERSION}}

vars:
PROJECT_NAME: "arduino-cli"
DIST_DIR: "dist"
Expand Down
32 changes: 18 additions & 14 deletions docs/installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,20 +58,22 @@ in your [`PATH`](https://en.wikipedia.org/wiki/PATH%5F%28variable%29) or add the

### Latest release

| Platform | | |
| --------- | -------------------- | -------------------- |
| Linux | [32 bit][linux32] | [64 bit][linux64] |
| Linux ARM | [32 bit][linuxarm32] | [64 bit][linuxarm64] |
| Windows | [32 bit][windows32] | [64 bit][windows64] |
| macOS | | [64 bit][macos64] |
| macOS ARM | | [64 bit][macosarm64] |
| Platform | | |
| ----------- | -------------------- | ---------------------- |
| Linux | [32 bit][linux32] | [64 bit][linux64] |
| Linux ARM | [32 bit][linuxarm32] | [64 bit][linuxarm64] |
| Windows exe | [32 bit][windows32] | [64 bit][windows64] |
| Windows msi | | [64 bit][windowsmsi64] |
| macOS | | [64 bit][macos64] |
| macOS ARM | | [64 bit][macosarm64] |

[linux64]: https://downloads.arduino.cc/arduino-cli/arduino-cli_latest_Linux_64bit.tar.gz
[linux32]: https://downloads.arduino.cc/arduino-cli/arduino-cli_latest_Linux_32bit.tar.gz
[linuxarm64]: https://downloads.arduino.cc/arduino-cli/arduino-cli_latest_Linux_ARM64.tar.gz
[linuxarm32]: https://downloads.arduino.cc/arduino-cli/arduino-cli_latest_Linux_ARMv7.tar.gz
[windows64]: https://downloads.arduino.cc/arduino-cli/arduino-cli_latest_Windows_64bit.zip
[windows32]: https://downloads.arduino.cc/arduino-cli/arduino-cli_latest_Windows_32bit.zip
[windowsmsi64]: https://downloads.arduino.cc/arduino-cli/arduino-cli_latest_Windows_64bit.msi
[macos64]: https://downloads.arduino.cc/arduino-cli/arduino-cli_latest_macOS_64bit.tar.gz
[macosarm64]: https://downloads.arduino.cc/arduino-cli/arduino-cli_latest_macOS_ARM64.tar.gz

Expand All @@ -88,20 +90,22 @@ These are available from the "Assets" sections on the [releases page](https://gi
These builds are generated every day at 01:00 GMT from the `master` branch and should be considered unstable. In order
to get the latest nightly build available for the supported platform, use the following links:

| Platform | | |
| --------- | ---------------------------- | ---------------------------- |
| Linux | [32 bit][linux32-nightly] | [64 bit][linux64-nightly] |
| Linux ARM | [32 bit][linuxarm32-nightly] | [64 bit][linuxarm64-nightly] |
| Windows | [32 bit][windows32-nightly] | [64 bit][windows64-nightly] |
| macOS | | [64 bit][macos64-nightly] |
| macOS ARM | | [64 bit][macosarm64-nightly] |
| Platform | | |
| ----------- | ---------------------------- | ------------------------------ |
| Linux | [32 bit][linux32-nightly] | [64 bit][linux64-nightly] |
| Linux ARM | [32 bit][linuxarm32-nightly] | [64 bit][linuxarm64-nightly] |
| Windows exe | [32 bit][windows32-nightly] | [64 bit][windows64-nightly] |
| Windows msi | | [64 bit][windowsmsi64-nightly] |
| macOS | | [64 bit][macos64-nightly] |
| macOS ARM | | [64 bit][macosarm64-nightly] |

[linux64-nightly]: https://downloads.arduino.cc/arduino-cli/nightly/arduino-cli_nightly-latest_Linux_64bit.tar.gz
[linux32-nightly]: https://downloads.arduino.cc/arduino-cli/nightly/arduino-cli_nightly-latest_Linux_32bit.tar.gz
[linuxarm64-nightly]: https://downloads.arduino.cc/arduino-cli/nightly/arduino-cli_nightly-latest_Linux_ARM64.tar.gz
[linuxarm32-nightly]: https://downloads.arduino.cc/arduino-cli/nightly/arduino-cli_nightly-latest_Linux_ARMv7.tar.gz
[windows64-nightly]: https://downloads.arduino.cc/arduino-cli/nightly/arduino-cli_nightly-latest_Windows_64bit.zip
[windows32-nightly]: https://downloads.arduino.cc/arduino-cli/nightly/arduino-cli_nightly-latest_Windows_32bit.zip
[windowsmsi64-nightly]: https://downloads.arduino.cc/arduino-cli/nightly/arduino-cli_nightly-latest_Windows_64bit.msi
[macos64-nightly]: https://downloads.arduino.cc/arduino-cli/nightly/arduino-cli_nightly-latest_macOS_64bit.tar.gz
[macosarm64-nightly]: https://downloads.arduino.cc/arduino-cli/nightly/arduino-cli_nightly-latest_macOS_ARM64.tar.gz

Expand Down
39 changes: 39 additions & 0 deletions installer/cli.wixproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration>Release</Configuration>
<Platform Condition="'$(Platform)' == ''">x64</Platform>
<!-- "ProductVersion" gets overridden when run with the commandline by the release CI, this is useful to define it if not defined -->
<ProductVersion Condition="'$(ProductVersion)' == ''">0.1.0</ProductVersion>
<!-- "OutputName" gets overridden when run with the commandline by the release CI, it's the name of the output file -->
<OutputName Condition="'$(OutputName)' == ''">$(MSBuildProjectName)</OutputName>
<OutputType>package</OutputType>
<DefineConstants>
$(DefineConstants);
ProductVersion=$(ProductVersion);
</DefineConstants>
<DefineSolutionProperties>false</DefineSolutionProperties>
<WixTargetsPath Condition="'$(WixTargetsPath)' == ''">$(MSBuildExtensionsPath)\Microsoft\WiX\v3.x\Wix.targets</WixTargetsPath>
</PropertyGroup>
<ItemGroup>
<!-- path and name of the additional files that contains additional config for the installer generation and needs Compile -->
<Compile Include="cli.wxs"/>
<Compile Include="ui.wxs"/>
</ItemGroup>
<ItemGroup>
<!-- Include directories containing both user-specified output and unzipped release for ease -->
<!-- "SourceDir" is defined when run with the commandline by the release CI, it's the folder containing files to include in the installer -->
<BindInputPaths Include="$(SourceDir)"/>
</ItemGroup>
<ItemGroup>
<!-- https://wixtoolset.org//documentation/manual/v3/wixui/wixui_dialog_library.html -->
<WixExtension Include="WixUIExtension"/>
<!-- we need the following to be able to broadcast the environment vars change -->
<WixExtension Include="WixUtilExtension"/>
</ItemGroup>
<Target Name="SetStepOutput" AfterTargets="Build" Condition="'$(GITHUB_ACTIONS)' != ''">
<!-- Define a GitHub Actions workflow step output containing the target path -->
<Message Importance="high" Text="::set-output name=msi::$(TargetPath)"/>
</Target>
<Import Project="$(WixTargetsPath)"/>
</Project>
Loading