Skip to content

feat: add windows amd64 installer #4719

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 7 commits into from
Oct 25, 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
7 changes: 5 additions & 2 deletions .github/workflows/release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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: |
Expand Down Expand Up @@ -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"
Expand Down Expand Up @@ -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 \
Expand Down
7 changes: 7 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:

Expand Down
125 changes: 125 additions & 0 deletions scripts/build_windows_installer.sh
Original file line number Diff line number Diff line change
@@ -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"
2 changes: 1 addition & 1 deletion scripts/package.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
Binary file added scripts/win-installer/banner.bmp
Binary file not shown.
Binary file added scripts/win-installer/coder.ico
Binary file not shown.
133 changes: 133 additions & 0 deletions scripts/win-installer/installer.nsi
Original file line number Diff line number Diff line change
@@ -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
Loading