feat: add windows amd64 installer (#4719)

This commit is contained in:
Dean Sheather 2022-10-26 00:19:54 +10:00 committed by GitHub
parent 7d04bf2abe
commit 067362cf31
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 473 additions and 4 deletions

View File

@ -65,13 +65,14 @@ jobs:
restore-keys: |
js-${{ runner.os }}-
- name: Install nsis and zstd
run: sudo apt-get install -y nsis zstd
- name: Install nfpm
run: |
set -euo pipefail
wget -O /tmp/nfpm.deb https://github.com/goreleaser/nfpm/releases/download/v2.18.1/nfpm_amd64.deb
sudo dpkg -i /tmp/nfpm.deb
- name: Install zstd
run: sudo apt-get install -y zstd
- name: Install rcodesign
run: |
@ -107,6 +108,7 @@ jobs:
make -j \
build/coder_"$version"_linux_{amd64,armv7,arm64}.{tar.gz,apk,deb,rpm} \
build/coder_"$version"_{darwin,windows}_{amd64,arm64}.zip \
build/coder_"$version"_windows_amd64_installer.exe \
build/coder_helm_"$version".tgz
env:
CODER_SIGN_DARWIN: "1"
@ -155,6 +157,7 @@ jobs:
run: |
./scripts/publish_release.sh \
${{ (github.event.inputs.dry_run || github.event.inputs.snapshot) && '--dry-run' }} \
./build/*_installer.exe \
./build/*.zip \
./build/*.tar.gz \
./build/*.tgz \

View File

@ -252,6 +252,13 @@ $(CODER_ALL_PACKAGES): $(CODER_PACKAGE_DEPS)
--output "$@" \
"build/coder_$(VERSION)_$${os}_$${arch}"
# This task builds a Windows amd64 installer. Depends on makensis.
build/coder_$(VERSION)_windows_amd64_installer.exe: build/coder_$(VERSION)_windows_amd64.exe
./scripts/build_windows_installer.sh \
--version "$(VERSION)" \
--output "$@" \
"$<"
# Redirect from version-less Docker image targets to the versioned ones.
#
# Called like this:

View File

@ -32,7 +32,10 @@ Coder creates remote development machines so your team can develop from anywhere
> **Note**:
> Coder is in a beta state. [Report issues here](https://github.com/coder/coder/issues/new).
The easiest way to install Coder is to use our [install script](https://github.com/coder/coder/blob/main/install.sh) for Linux and macOS.
The easiest way to install Coder is to use our
[install script](https://github.com/coder/coder/blob/main/install.sh) for Linux
and macOS. For Windows, use the latest `..._installer.exe` file from GitHub
Releases.
To install, run:

View File

@ -0,0 +1,125 @@
#!/usr/bin/env bash
# This script packages a Windows installer for Coder containing the given
# binary.
#
# Usage: ./build_windows_installer.sh --output "path/to/installer.exe" [--version 1.2.3] [--agpl] path/to/binary.exe
#
# Only amd64 binaries are supported.
#
# If no version is specified, defaults to the version from ./version.sh.
#
# If the --agpl parameter is specified, only the AGPL license is included in the
# installer.
set -euo pipefail
# shellcheck source=scripts/lib.sh
source "$(dirname "${BASH_SOURCE[0]}")/lib.sh"
agpl="${CODER_BUILD_AGPL:-0}"
output_path=""
version=""
args="$(getopt -o "" -l agpl,output:,version: -- "$@")"
eval set -- "$args"
while true; do
case "$1" in
--agpl)
agpl=1
shift
;;
--output)
mkdir -p "$(dirname "$2")"
output_path="$(realpath "$2")"
shift 2
;;
--version)
version="$2"
shift 2
;;
--)
shift
break
;;
*)
error "Unrecognized option: $1"
;;
esac
done
if [[ "$output_path" == "" ]]; then
error "--output is a required parameter"
fi
if [[ "$#" != 1 ]]; then
error "Exactly one argument must be provided to this script, $# were supplied"
fi
if [[ ! -f "$1" ]]; then
error "File '$1' does not exist or is not a regular file"
fi
input_file="$(realpath "$1")"
version="${version#v}"
if [[ "$version" == "" ]]; then
version="$(execrelative ./version.sh)"
fi
# Remove the "v" prefix and ensure the version is in the format X.X.X.X for
# makensis.
nsis_version="${version//-*/}"
nsis_version+=".$(date -u +%Y%m%d%H%M)"
# Check dependencies
dependencies makensis
# Make a temporary dir where all source files intended to be in the installer
# will be hardlinked/copied to.
cdroot
temp_dir="$(TMPDIR="$(dirname "$input_file")" mktemp -d)"
mkdir -p "$temp_dir/bin"
ln "$input_file" "$temp_dir/bin/coder.exe"
cp "$(realpath scripts/win-installer/installer.nsi)" "$temp_dir/installer.nsi"
cp "$(realpath scripts/win-installer/path.nsh)" "$temp_dir/path.nsh"
cp "$(realpath scripts/win-installer/coder.ico)" "$temp_dir/coder.ico"
cp "$(realpath scripts/win-installer/banner.bmp)" "$temp_dir/banner.bmp"
# Craft a license document by combining the AGPL license and optionally the
# enterprise license.
license_path="$temp_dir/license.txt"
if [[ "$agpl" == 0 ]]; then
cat <<-EOF >"$license_path"
This distribution of Coder includes some enterprise-licensed code which is not
licensed under the AGPL license:
$(sed 's/^/ /' "$(realpath LICENSE.enterprise)")
The non-enterprise code in this distribution is licensed under the AGPL license:
$(sed 's/^/ /' "$(realpath LICENSE)")
EOF
else
cat <<-EOF >"$license_path"
This distribution of Coder is free software and is licensed under the AGPL
license:
$(sed 's/^/ /' "$(realpath LICENSE)")
EOF
fi
# Run makensis to build the installer.
pushd "$temp_dir"
makensis \
-V4 \
-DCODER_VERSION="$version" \
-DCODER_NSIS_VERSION="$nsis_version" \
-DCODER_YEAR="$(date +%Y)" \
installer.nsi
popd
# Copy the installer to the output path.
cp "$temp_dir/installer.exe" "$output_path"
rm -rf "$temp_dir"

View File

@ -79,7 +79,7 @@ if [[ "$arch" == "arm" ]] || [[ "$arch" == "armv7" ]]; then
fi
# Make temporary dir where all source files intended to be in the package will
# be hardlinked from.
# be hardlinked to.
cdroot
temp_dir="$(TMPDIR="$(dirname "$input_file")" mktemp -d)"
ln "$input_file" "$temp_dir/coder"

Binary file not shown.

After

Width:  |  Height:  |  Size: 151 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 422 KiB

View File

@ -0,0 +1,133 @@
# This NSIS installer script was taken from the following webpage and heavily
# adapted to Coder's needs:
# https://www.conjur.org/blog/building-a-windows-installer-from-a-linux-ci-pipeline/
Unicode true
!define APP_NAME "Coder"
!define COMP_NAME "Coder Technologies, Inc."
!define VERSION "${CODER_NSIS_VERSION}"
!define COPYRIGHT "Copyright (c) ${CODER_YEAR} Coder Technologies, Inc."
!define DESCRIPTION "Remote development environments on your infrastructure provisioned with Terraform"
!define INSTALLER_NAME "installer.exe"
!define MAIN_APP_EXE "coder.exe"
!define MAIN_APP_EXE_PATH "bin\coder.exe"
!define ICON "coder.ico"
!define BANNER "banner.bmp"
!define LICENSE_TXT "license.txt"
!define INSTALL_DIR "$PROGRAMFILES64\${APP_NAME}"
!define INSTALL_TYPE "SetShellVarContext all" # this means install for all users
!define REG_ROOT "HKLM"
!define REG_APP_PATH "Software\Microsoft\Windows\CurrentVersion\App Paths\${MAIN_APP_EXE}"
!define UNINSTALL_PATH "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APP_NAME}"
######################################################################
VIProductVersion "${VERSION}"
VIAddVersionKey "ProductName" "${APP_NAME}"
VIAddVersionKey "CompanyName" "${COMP_NAME}"
VIAddVersionKey "LegalCopyright" "${COPYRIGHT}"
VIAddVersionKey "FileDescription" "${DESCRIPTION}"
VIAddVersionKey "FileVersion" "${VERSION}"
######################################################################
SetCompressor /SOLID Lzma
Name "${APP_NAME}"
Caption "${APP_NAME}"
OutFile "${INSTALLER_NAME}"
BrandingText "${APP_NAME} v${CODER_VERSION}"
InstallDirRegKey "${REG_ROOT}" "${REG_APP_PATH}" "Path"
InstallDir "${INSTALL_DIR}"
######################################################################
!define MUI_ICON "${ICON}"
!define MUI_UNICON "${ICON}"
!define MUI_WELCOMEFINISHPAGE_BITMAP "${BANNER}"
!define MUI_UNWELCOMEFINISHPAGE_BITMAP "${BANNER}"
######################################################################
!include "MUI2.nsh"
!define MUI_ABORTWARNING
!define MUI_UNABORTWARNING
!define MUI_WELCOMEPAGE_TEXT "Setup will guide you through the installation of Coder v${CODER_VERSION}.$\r$\n$\r$\nClick Next to continue."
!insertmacro MUI_PAGE_WELCOME
!insertmacro MUI_PAGE_LICENSE "${LICENSE_TXT}"
!insertmacro MUI_PAGE_COMPONENTS
!insertmacro MUI_PAGE_DIRECTORY
!insertmacro MUI_PAGE_INSTFILES
!define MUI_FINISHPAGE_TEXT "Coder v${CODER_VERSION} has been installed on your computer.$\r$\n$\r$\nIf you added Coder to your PATH, you can use Coder by opening a command prompt or PowerShell and running `coder`. You may have to sign out and sign back in for `coder` to be available.$\r$\n$\r$\nClick Finish to close Setup."
!insertmacro MUI_PAGE_FINISH
!insertmacro MUI_UNPAGE_CONFIRM
!insertmacro MUI_UNPAGE_INSTFILES
!insertmacro MUI_UNPAGE_FINISH
!insertmacro MUI_LANGUAGE "English"
######################################################################
!include ".\path.nsh"
Section "Coder CLI" SecInstall
SectionIn RO # mark this section as required
${INSTALL_TYPE}
SetOverwrite ifnewer
SetOutPath "$INSTDIR"
File /r "bin"
File "${LICENSE_TXT}"
WriteUninstaller "$INSTDIR\uninstall.exe"
WriteRegStr ${REG_ROOT} "${REG_APP_PATH}" "" "$INSTDIR\${MAIN_APP_EXE_PATH}"
WriteRegStr ${REG_ROOT} "${REG_APP_PATH}" "Path" "$INSTDIR"
WriteRegStr ${REG_ROOT} "${UNINSTALL_PATH}" "DisplayName" "${APP_NAME}"
WriteRegStr ${REG_ROOT} "${UNINSTALL_PATH}" "UninstallString" "$INSTDIR\uninstall.exe"
WriteRegStr ${REG_ROOT} "${UNINSTALL_PATH}" "DisplayIcon" "$INSTDIR\${MAIN_APP_EXE_PATH}"
WriteRegStr ${REG_ROOT} "${UNINSTALL_PATH}" "DisplayVersion" "${VERSION}"
WriteRegStr ${REG_ROOT} "${UNINSTALL_PATH}" "Publisher" "${COMP_NAME}"
SectionEnd
Section "Add to PATH" SecAddToPath
Push "$INSTDIR\bin"
Call AddToPath
SectionEnd
######################################################################
Section Uninstall
${INSTALL_TYPE}
RmDir /r "$INSTDIR"
DeleteRegKey ${REG_ROOT} "${REG_APP_PATH}"
DeleteRegKey ${REG_ROOT} "${UNINSTALL_PATH}"
Push "$INSTDIR\bin"
Call un.RemoveFromPath
SectionEnd
######################################################################
LangString DESC_SecInstall ${LANG_ENGLISH} "Install the Coder command-line interface (coder.exe) for all users."
LangString DESC_SecAddToPath ${LANG_ENGLISH} "Add coder.exe to the PATH for all users. This enables `coder` to be used directly from a command prompt or PowerShell."
!insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN
!insertmacro MUI_DESCRIPTION_TEXT ${SecInstall} $(DESC_SecInstall)
!insertmacro MUI_DESCRIPTION_TEXT ${SecAddToPath} $(DESC_SecAddToPath)
!insertmacro MUI_FUNCTION_DESCRIPTION_END

View File

@ -0,0 +1,198 @@
# PATH utilities. Taken from:
# https://www.smartmontools.org/browser/trunk/smartmontools/os_win32/installer.nsi?rev=5310#L689
; os_win32/installer.nsi - smartmontools install NSIS script
;
; Home page of code is: https://www.smartmontools.org
;
; Copyright (C) 2006-22 Christian Franke
;
; SPDX-License-Identifier: GPL-2.0-or-later
;--------------------------------------------------------------------
; Path functions
;
; Based on example from:
; http://nsis.sourceforge.net/Path_Manipulation
;
!include "WinMessages.nsh"
; Registry Entry for environment (NT4,2000,XP)
; All users:
!define Environ 'HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"'
; Current user only:
;!define Environ 'HKCU "Environment"'
; AddToPath - Appends dir to PATH
; (does not work on Win9x/ME)
;
; Usage:
; Push "dir"
; Call AddToPath
Function AddToPath
Exch $0
Push $1
Push $2
Push $3
Push $4
; NSIS ReadRegStr returns empty string on string overflow
; Native calls are used here to check actual length of PATH
; $4 = RegOpenKey(HKEY_CURRENT_USER, "Environment", &$3)
System::Call "advapi32::RegOpenKey(i 0x80000001, t'Environment', *i.r3) i.r4"
IntCmp $4 0 0 done done
; $4 = RegQueryValueEx($3, "PATH", (DWORD*)0, (DWORD*)0, &$1, ($2=NSIS_MAX_STRLEN, &$2))
; RegCloseKey($3)
System::Call "advapi32::RegQueryValueEx(i $3, t'PATH', i 0, i 0, t.r1, *i ${NSIS_MAX_STRLEN} r2) i.r4"
System::Call "advapi32::RegCloseKey(i $3)"
${If} $4 = 234 ; ERROR_MORE_DATA
DetailPrint "AddToPath: original length $2 > ${NSIS_MAX_STRLEN}"
MessageBox MB_OK "PATH not updated, original length $2 > ${NSIS_MAX_STRLEN}" /SD IDOK
Goto done
${EndIf}
${If} $4 <> 0 ; NO_ERROR
${If} $4 <> 2 ; ERROR_FILE_NOT_FOUND
DetailPrint "AddToPath: unexpected error code $4"
Goto done
${EndIf}
StrCpy $1 ""
${EndIf}
; Check if already in PATH
Push "$1;"
Push "$0;"
Call StrStr
Pop $2
StrCmp $2 "" 0 done
Push "$1;"
Push "$0\;"
Call StrStr
Pop $2
StrCmp $2 "" 0 done
; Prevent NSIS string overflow
StrLen $2 $0
StrLen $3 $1
IntOp $2 $2 + $3
IntOp $2 $2 + 2 ; $2 = strlen(dir) + strlen(PATH) + sizeof(";")
${If} $2 > ${NSIS_MAX_STRLEN}
DetailPrint "AddToPath: new length $2 > ${NSIS_MAX_STRLEN}"
MessageBox MB_OK "PATH not updated, new length $2 > ${NSIS_MAX_STRLEN}." /SD IDOK
Goto done
${EndIf}
; Append dir to PATH
DetailPrint "Add to PATH: $0"
StrCpy $2 $1 1 -1
${If} $2 == ";"
StrCpy $1 $1 -1 ; remove trailing ';'
${EndIf}
${If} $1 != "" ; no leading ';'
StrCpy $0 "$1;$0"
${EndIf}
WriteRegExpandStr ${Environ} "PATH" $0
SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000
done:
Pop $4
Pop $3
Pop $2
Pop $1
Pop $0
FunctionEnd
; RemoveFromPath - Removes dir from PATH
;
; Usage:
; Push "dir"
; Call RemoveFromPath
Function un.RemoveFromPath
Exch $0
Push $1
Push $2
Push $3
Push $4
Push $5
Push $6
ReadRegStr $1 ${Environ} "PATH"
StrCpy $5 $1 1 -1
${If} $5 != ";"
StrCpy $1 "$1;" ; ensure trailing ';'
${EndIf}
Push $1
Push "$0;"
Call un.StrStr
Pop $2 ; pos of our dir
StrCmp $2 "" done
DetailPrint "Remove from PATH: $0"
StrLen $3 "$0;"
StrLen $4 $2
StrCpy $5 $1 -$4 ; $5 is now the part before the path to remove
StrCpy $6 $2 "" $3 ; $6 is now the part after the path to remove
StrCpy $3 "$5$6"
StrCpy $5 $3 1 -1
${If} $5 == ";"
StrCpy $3 $3 -1 ; remove trailing ';'
${EndIf}
WriteRegExpandStr ${Environ} "PATH" $3
SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000
done:
Pop $6
Pop $5
Pop $4
Pop $3
Pop $2
Pop $1
Pop $0
FunctionEnd
; StrStr - find substring in a string
;
; Usage:
; Push "this is some string"
; Push "some"
; Call StrStr
; Pop $0 ; "some string"
!macro StrStr un
Function ${un}StrStr
Exch $R1 ; $R1=substring, stack=[old$R1,string,...]
Exch ; stack=[string,old$R1,...]
Exch $R2 ; $R2=string, stack=[old$R2,old$R1,...]
Push $R3
Push $R4
Push $R5
StrLen $R3 $R1
StrCpy $R4 0
; $R1=substring, $R2=string, $R3=strlen(substring)
; $R4=count, $R5=tmp
${Do}
StrCpy $R5 $R2 $R3 $R4
${IfThen} $R5 == $R1 ${|} ${ExitDo} ${|}
${IfThen} $R5 == "" ${|} ${ExitDo} ${|}
IntOp $R4 $R4 + 1
${Loop}
StrCpy $R1 $R2 "" $R4
Pop $R5
Pop $R4
Pop $R3
Pop $R2
Exch $R1 ; $R1=old$R1, stack=[result,...]
FunctionEnd
!macroend
!insertmacro StrStr ""
!insertmacro StrStr "un."