diff --git a/.github/workflows/check-certificates.yml b/.github/workflows/check-certificates.yml index 589dd2412ed..9ca01502255 100644 --- a/.github/workflows/check-certificates.yml +++ b/.github/workflows/check-certificates.yml @@ -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 diff --git a/.github/workflows/publish-go-nightly-task.yml b/.github/workflows/publish-go-nightly-task.yml index 6ddc4e7e7fc..821673c8ce0 100644 --- a/.github/workflows/publish-go-nightly-task.yml +++ b/.github/workflows/publish-go-nightly-task.yml @@ -20,6 +20,8 @@ on: jobs: create-nightly-artifacts: + outputs: + version: ${{ steps.get-version.outputs.version }} runs-on: ubuntu-latest strategy: @@ -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: @@ -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 @@ -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 @@ -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 @@ -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 diff --git a/.github/workflows/release-go-task.yml b/.github/workflows/release-go-task.yml index 8c27721899e..5d026f422bb 100644 --- a/.github/workflows/release-go-task.yml +++ b/.github/workflows/release-go-task.yml @@ -17,6 +17,8 @@ on: jobs: create-release-artifacts: + outputs: + version: ${{ steps.get-version.outputs.version }} runs-on: ubuntu-latest strategy: @@ -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: @@ -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 @@ -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 }}" \ @@ -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 @@ -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 @@ -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 diff --git a/.prettierignore b/.prettierignore index 26aad378ce1..3b34afa1ed6 100644 --- a/.prettierignore +++ b/.prettierignore @@ -8,3 +8,4 @@ /arduino/security/testdata/ /.licenses/ /site/ +/installer/ \ No newline at end of file diff --git a/Taskfile.yml b/Taskfile.yml index 9d24febc3b1..23a2b6561aa 100755 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -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" diff --git a/docs/installation.md b/docs/installation.md index 9677997ac43..6a444fe4bfc 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -58,13 +58,14 @@ 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 @@ -72,6 +73,7 @@ in your [`PATH`](https://en.wikipedia.org/wiki/PATH%5F%28variable%29) or add the [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 @@ -88,13 +90,14 @@ 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 @@ -102,6 +105,7 @@ to get the latest nightly build available for the supported platform, use the fo [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 diff --git a/installer/cli.wixproj b/installer/cli.wixproj new file mode 100644 index 00000000000..e574aa9f168 --- /dev/null +++ b/installer/cli.wixproj @@ -0,0 +1,39 @@ + + + + Release + x64 + + 0.1.0 + + $(MSBuildProjectName) + package + + $(DefineConstants); + ProductVersion=$(ProductVersion); + + false + $(MSBuildExtensionsPath)\Microsoft\WiX\v3.x\Wix.targets + + + + + + + + + + + + + + + + + + + + + + + diff --git a/installer/cli.wxs b/installer/cli.wxs new file mode 100644 index 00000000000..0a3731edda2 --- /dev/null +++ b/installer/cli.wxs @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/installer/ui.wxs b/installer/ui.wxs new file mode 100644 index 00000000000..5de8cf2c3d7 --- /dev/null +++ b/installer/ui.wxs @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + + + + + 1 + "1"]]> + + 1 + + NOT Installed + Installed AND PATCH + + 1 + 1 + NOT WIXUI_DONTVALIDATEPATH + "1"]]> + WIXUI_DONTVALIDATEPATH OR WIXUI_INSTALLDIR_VALID="1" + 1 + 1 + + NOT Installed + Installed AND NOT PATCH + Installed AND PATCH + + 1 + + 1 + 1 + 1 + + + + + + + \ No newline at end of file