Skip to content

Commit

Permalink
Merge pull request #27 from harness/msi
Browse files Browse the repository at this point in the history
Created msi installer for windows
  • Loading branch information
abhay084 authored Apr 1, 2024
2 parents 50b1bc6 + 538b927 commit 8c38321
Show file tree
Hide file tree
Showing 10 changed files with 347 additions and 3 deletions.
41 changes: 40 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Lite-engine
# Harness-Docker-Runner

How to use:

Expand All @@ -8,6 +8,45 @@ How to use:
* Start server: go run main.go server
* Client call to check health status of server: go run main.go client.

### Instruction for Running it as Windows Service

If you want to install Harness-Docker-Runner as a service in Windows, please follow the bellow instructions.

#### Instruction for creating msi from Exe file
* choco install go-msi (https://github.com/mh-cbon/go-msi)
* create the binary for harness-docker-runner-windows-amd64.exe
```
go build -o harness-docker-runner-windows-amd64.exe
```
* run the below command from root directory of Harness-Docker-Runner to create msi
```
go-msi make --msi harness-docker-runner-svc.msi --version your_version
```

#### Installation
* Download the msi (harness-docker-runner-svc.msi) from latest github release
* Double click on the msi to start the installation process
* Accept the liecence, click next and finish the installation.
* You can test your service availibility by running below command in your cmd terminal
```
curl http://localhost:3000/healthz
```
* Logs for the runner can be found in path : C:\Windows\system32\harness-docker-runner-timestamp.log

#### Uninstallation
* Double click on the msi to start the installation process
* You will see three options Change, Repair and Remove
* Click on Remove and finish.

#### Additional Instructions
* Service will automatically started even if you re-started your VM
* Please do not attemp to start/stop/delete the service manually, it may cause issue in uninstallation.
* In case you see any issues and not able to verfiy the runner, Uninstall and install again using the msi

#### Error and Resolutions
* For the below both the error, we need to give a full permission to our msi file to get it working. Since this is an extenal msi which is not trusted by windows security, it blocks it initially which can be handle by manually assigning the required permissions from Properties => Security tab.
* If you are facing Error code 2502 or 2503 during installation, please follow the below instruction or link: https://help.krisp.ai/hc/en-us/articles/8083286001820-Error-during-installation-2502-and-2503#h_01HNCW0XCN8AJCWK84K8MQVY7Y
* For error "This installation package could not be opened" then please follow this link: https://answers.microsoft.com/en-us/windows/forum/all/this-installation-package-could-not-be/d6d913e9-aac7-429a-ac0d-c39ad3a7c5eb
## Release procedure

Run the changelog generator.
Expand Down
16 changes: 16 additions & 0 deletions cli/server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import (
"fmt"
"os"
"os/signal"
RunTime "runtime"
"time"

"github.com/harness/harness-docker-runner/config"
"github.com/harness/harness-docker-runner/engine"
Expand Down Expand Up @@ -142,4 +144,18 @@ func initLogging(c *config.Config) {
if c.Trace {
l.SetLevel(logrus.TraceLevel)
}

if RunTime.GOOS == "windows" {
dir, _ := os.Getwd()
logFilePath := dir + string(os.PathSeparator) + "harness-docker-runner-" + time.Now().Format("2-January-2006") + ".log"
logrus.Infoln("Logs will be dumped to : " + logFilePath)
file, err := os.OpenFile(logFilePath, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
if err != nil {
logger.L.Logger.Infoln("Failed to open log file:", err)
}

// Set the logger's output to the file
logger.L.Logger.SetOutput(file)
}

}
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ require (
)

require (
github.com/kardianos/service v1.2.2 // indirect
github.com/99designs/httpsignatures-go v0.0.0-20170731043157-88528bf4ca7e // indirect
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect
github.com/Microsoft/go-winio v0.6.0 // indirect
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -612,6 +612,8 @@ github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/X
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
github.com/kardianos/service v1.2.2 h1:ZvePhAHfvo0A7Mftk/tEzqEZ7Q4lgnR8sGz4xu1YX60=
github.com/kardianos/service v1.2.2/go.mod h1:CIMRFEJVL+0DS1a3Nx06NaMn4Dz63Ng6O7dl0qH0zVM=
github.com/kelseyhightower/envconfig v1.4.0 h1:Im6hONhd3pLkfDFsbRgu68RDNkGF1r3dvMUtDTo2cv8=
github.com/kelseyhightower/envconfig v1.4.0/go.mod h1:cccZRl6mQpaq41TPp5QxidR+Sa3axMbJDNb//FQX6Gg=
github.com/keybase/go-ps v0.0.0-20190827175125-91aafc93ba19 h1:WjT3fLi9n8YWh/Ih8Q1LHAPsTqGddPcHqscN+PJ3i68=
Expand Down
40 changes: 38 additions & 2 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,47 @@
package main

import (
"github.com/harness/harness-docker-runner/cli"
"runtime"

"github.com/harness/harness-docker-runner/cli"
_ "github.com/joho/godotenv/autoload"
"github.com/kardianos/service"
)

func main() {
cli.Command()
if runtime.GOOS == "windows" {
svcConfig := &service.Config{
Name: "harness-docker-runner-svc",
DisplayName: "harness-docker-runner-svc",
Description: "This is a service runing for harness-docker-runner",
}

runAsService(svcConfig, func() {
cli.Command()
})
} else {
cli.Command()
}
}

func runAsService(svcConfig *service.Config, run func()) error {
s, err := service.New(&program{exec: run}, svcConfig)
if err != nil {
return err
}
return s.Run()
}

type program struct {
exec func()
}

func (p *program) Start(s service.Service) error {
// Start should not block. Do the actual work async.
go p.exec()
return nil
}
func (p *program) Stop(s service.Service) error {
// Stop should not block. Return with a few seconds.
return nil
}
35 changes: 35 additions & 0 deletions templates/LicenseAgreementDlg_HK.wxs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?xml version="1.0" encoding="UTF-8"?>

<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Fragment>
<UI>
<Dialog Id="LicenseAgreementDlg_HK" Width="370" Height="270" Title="!(loc.LicenseAgreementDlg_Title)">
<Control Id="LicenseAcceptedCheckBox" Type="CheckBox" X="20" Y="207" Width="330" Height="18" CheckBoxValue="1" Property="LicenseAccepted" Text="!(loc.LicenseAgreementDlgLicenseAcceptedCheckBox)" />
<Control Id="Back" Type="PushButton" X="180" Y="243" Width="56" Height="17" Text="!(loc.WixUIBack)" />
<Control Id="Next" Type="PushButton" X="236" Y="243" Width="56" Height="17" Default="yes" Text="!(loc.WixUINext)">
<Publish Event="SpawnWaitDialog" Value="WaitForCostingDlg">CostingComplete = 1</Publish>
<Condition Action="disable">
<![CDATA[LicenseAccepted <> "1"]]>
</Condition>
<Condition Action="enable">LicenseAccepted = "1"</Condition>
</Control>
<Control Id="Cancel" Type="PushButton" X="304" Y="243" Width="56" Height="17" Cancel="yes" Text="!(loc.WixUICancel)">
<Publish Event="SpawnDialog" Value="CancelDlg">1</Publish>
</Control>
<Control Id="BannerBitmap" Type="Bitmap" X="0" Y="0" Width="370" Height="44" TabSkip="no" Text="!(loc.LicenseAgreementDlgBannerBitmap)" />
<Control Id="LicenseText" Type="ScrollableText" X="20" Y="60" Width="330" Height="140" Sunken="yes" TabSkip="no">
{{if gt (.License | len) 0}}
<Text SourceFile="{{.License}}" />
{{end}}
</Control>
<Control Id="Print" Type="PushButton" X="112" Y="243" Width="56" Height="17" Text="!(loc.WixUIPrint)">
<Publish Event="DoAction" Value="WixUIPrintEula">1</Publish>
</Control>
<Control Id="BannerLine" Type="Line" X="0" Y="44" Width="370" Height="0" />
<Control Id="BottomLine" Type="Line" X="0" Y="234" Width="370" Height="0" />
<Control Id="Description" Type="Text" X="25" Y="23" Width="340" Height="15" Transparent="yes" NoPrefix="yes" Text="!(loc.LicenseAgreementDlgDescription)" />
<Control Id="Title" Type="Text" X="15" Y="6" Width="200" Height="15" Transparent="yes" NoPrefix="yes" Text="!(loc.LicenseAgreementDlgTitle)" />
</Dialog>
</UI>
</Fragment>
</Wix>
62 changes: 62 additions & 0 deletions templates/WixUI_HK.wxs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Fragment>
<UI Id="WixUI_HK">
<TextStyle Id="WixUI_Font_Normal" FaceName="Tahoma" Size="8" />
<TextStyle Id="WixUI_Font_Bigger" FaceName="Tahoma" Size="12" />
<TextStyle Id="WixUI_Font_Title" FaceName="Tahoma" Size="9" Bold="yes" />

<Property Id="DefaultUIFont" Value="WixUI_Font_Normal" />
<Property Id="WixUI_Mode" Value="InstallDir" />

<DialogRef Id="BrowseDlg" />
<DialogRef Id="DiskCostDlg" />
<DialogRef Id="ErrorDlg" />
<DialogRef Id="FatalError" />
<DialogRef Id="FilesInUse" />
<DialogRef Id="MsiRMFilesInUse" />
<DialogRef Id="PrepareDlg" />
<DialogRef Id="ProgressDlg" />
<DialogRef Id="ResumeDlg" />
<DialogRef Id="UserExit" />

<!-- Make sure to include custom dialogs in the installer database via a DialogRef command,
especially if they are not included explicitly in the publish chain below -->
<DialogRef Id="LicenseAgreementDlg_HK" />

<Publish Dialog="BrowseDlg" Control="OK" Event="DoAction" Value="WixUIValidatePath" Order="3">1</Publish>
<Publish Dialog="BrowseDlg" Control="OK" Event="SpawnDialog" Value="InvalidDirDlg" Order="4">
<![CDATA[WIXUI_INSTALLDIR_VALID<>"1"]]>
</Publish>

<Publish Dialog="ExitDialog" Control="Finish" Event="EndDialog" Value="Return" Order="999">1</Publish>

<Publish Dialog="WelcomeDlg" Control="Next" Event="NewDialog" {{if gt (.License | len) 0}} Value="LicenseAgreementDlg_HK" {{else}} Value="InstallDirDlg" {{end}}>NOT Installed</Publish>
<Publish Dialog="WelcomeDlg" Control="Next" Event="NewDialog" Value="VerifyReadyDlg">Installed AND PATCH</Publish>

<Publish Dialog="LicenseAgreementDlg_HK" Control="Back" Event="NewDialog" Value="WelcomeDlg">1</Publish>
<Publish Dialog="LicenseAgreementDlg_HK" Control="Next" Event="NewDialog" Value="InstallDirDlg">LicenseAccepted = "1"</Publish>

<Publish Dialog="InstallDirDlg" Control="Back" Event="NewDialog" Value="LicenseAgreementDlg_HK">1</Publish>
<Publish Dialog="InstallDirDlg" Control="Next" Event="SetTargetPath" Value="[WIXUI_INSTALLDIR]" Order="1">1</Publish>
<Publish Dialog="InstallDirDlg" Control="Next" Event="DoAction" Value="WixUIValidatePath" Order="2">NOT WIXUI_DONTVALIDATEPATH</Publish>
<Publish Dialog="InstallDirDlg" Control="Next" Event="SpawnDialog" Value="InvalidDirDlg" Order="3">
<![CDATA[NOT WIXUI_DONTVALIDATEPATH AND WIXUI_INSTALLDIR_VALID<>"1"]]>
</Publish>
<Publish Dialog="InstallDirDlg" Control="Next" Event="NewDialog" Value="VerifyReadyDlg" Order="4">WIXUI_DONTVALIDATEPATH OR WIXUI_INSTALLDIR_VALID="1"</Publish>

<Publish Dialog="InstallDirDlg" Control="ChangeFolder" Property="_BrowseProperty" Value="[WIXUI_INSTALLDIR]" Order="1">1</Publish>
<Publish Dialog="InstallDirDlg" Control="ChangeFolder" Event="SpawnDialog" Value="BrowseDlg" Order="2">1</Publish>

<Publish Dialog="VerifyReadyDlg" Control="Back" Event="NewDialog" Value="MaintenanceTypeDlg" Order="2">Installed</Publish>

<Publish Dialog="MaintenanceWelcomeDlg" Control="Next" Event="NewDialog" Value="MaintenanceTypeDlg">1</Publish>

<Publish Dialog="MaintenanceTypeDlg" Control="RepairButton" Event="NewDialog" Value="VerifyReadyDlg">1</Publish>
<Publish Dialog="MaintenanceTypeDlg" Control="RemoveButton" Event="NewDialog" Value="VerifyReadyDlg">1</Publish>
<Publish Dialog="MaintenanceTypeDlg" Control="Back" Event="NewDialog" Value="MaintenanceWelcomeDlg">1</Publish>
</UI>

<UIRef Id="WixUI_Common" />
</Fragment>
</Wix>
114 changes: 114 additions & 0 deletions templates/product.wxs
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
<?xml version="1.0"?>

<?if $(sys.BUILDARCH)="x86" ?>
<?define Program_Files="ProgramFilesFolder" ?>
<?elseif $(sys.BUILDARCH)="x64" ?>
<?define Program_Files="ProgramFiles64Folder" ?>
<?else ?>
<?error Unsupported value of sys.BUILDARCH=$(sys.BUILDARCH) ?>
<?endif ?>

<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">

<Product Id="*" UpgradeCode="{{.UpgradeCode}}" Name="{{.Product}}" Version="{{.VersionOk}}" Manufacturer="{{.Company}}" Language="1033">

<Package InstallerVersion="200" Compressed="yes" Comments="Windows Installer Package" InstallScope="perMachine" />

<Media Id="1" Cabinet="product.cab" EmbedCab="yes" />

<Upgrade Id="{{.UpgradeCode}}">
<UpgradeVersion Minimum="{{.VersionOk}}" OnlyDetect="yes" Property="NEWERVERSIONDETECTED" />
<UpgradeVersion Minimum="0.0.0" Maximum="{{.VersionOk}}" IncludeMinimum="yes" IncludeMaximum="no" Property="OLDERVERSIONBEINGUPGRADED" />
</Upgrade>
<Condition Message="A newer version of this software is already installed.">NOT NEWERVERSIONDETECTED</Condition>

<Directory Id="TARGETDIR" Name="SourceDir">

<Directory Id="$(var.Program_Files)">
<Directory Id="INSTALLDIR" Name="{{.Product}}">
{{if gt (.Files.Items | len) 0}}
<Component Id="ApplicationFiles" Guid="{{.Files.GUID}}">
{{range $i, $e := .Files.Items}}
<File Id="ApplicationFile{{$i}}" Source="{{$e}}" />
{{end}}
</Component>
{{end}}
{{if gt (.Directories | len) 0}}
{{range $i, $e := .Directories}}
<Directory Id="APPDIR{{$i}}" Name="{{$e}}" />
{{end}}
{{end}}
</Directory>
</Directory>
{{if gt (.Env.Vars | len) 0}}
<Component Id="ENVS" Guid="{{.Env.GUID}}">
{{range $i, $e := .Env.Vars}}
<Environment Id="ENV{{$i}}" Name="{{$e.Name}}" Value="{{$e.Value}}" Permanent="{{$e.Permanent}}" Part="{{$e.Part}}" Action="{{$e.Action}}" System="{{$e.System}}" />
{{end}}
</Component>
{{end}}

{{if gt (.Shortcuts.Items | len) 0}}
<Directory Id="ProgramMenuFolder">
<Directory Id="ProgramMenuSubfolder" Name="{{.Product}}">
<Component Id="ApplicationShortcuts" Guid="{{.Shortcuts.GUID}}">
{{range $i, $e := .Shortcuts.Items}}
<Shortcut Id="ApplicationShortcut{{$i}}" Name="{{$e.Name}}" Description="{{$e.Description}}" Target="{{$e.Target}}" WorkingDirectory="{{$e.WDir}}" {{if gt ($e.Arguments | len) 0}} Arguments="{{$e.Arguments}}" {{end}}>
{{if gt ($e.Icon | len) 0}}
<Icon Id="Icon{{$i}}" SourceFile="{{$e.Icon}}" />
{{end}}
</Shortcut>
<RegistryValue Root="HKCU" Key="Software\{{$.Company}}\{{$.Product}}" Name="installed{{$i}}" Type="integer" Value="1" KeyPath="yes" />
{{end}}
<RemoveFolder Id="ProgramMenuSubfolder" On="uninstall" />
</Component>
</Directory>
</Directory>
{{end}}
</Directory>
{{range $i, $e := .InstallHooks}}
<SetProperty Id="CustomInstallExec{{$i}}" Value="{{$e.CookedCommand}}" Before="CustomInstallExec{{$i}}" Sequence="execute" />
<CustomAction Id="CustomInstallExec{{$i}}" BinaryKey="WixCA" DllEntry="WixQuietExec" Execute="deferred" Return="check" Impersonate="no" />
{{end}}
{{range $i, $e := .UninstallHooks}}
<SetProperty Id="CustomUninstallExec{{$i}}" Value="{{$e.CookedCommand}}" Before="CustomUninstallExec{{$i}}" Sequence="execute" />
<CustomAction Id="CustomUninstallExec{{$i}}" BinaryKey="WixCA" DllEntry="WixQuietExec" Execute="deferred" Return="check" Impersonate="no" />
{{end}}
<InstallExecuteSequence>
<RemoveExistingProducts After="InstallValidate" />
{{range $i, $e := .InstallHooks}}
<Custom Action="CustomInstallExec{{$i}}" After="{{if eq $i 0}}InstallFiles{{else}}CustomInstallExec{{dec $i}}{{end}}">NOT Installed AND NOT REMOVE</Custom>
{{end}}
{{range $i, $e := .UninstallHooks}}
<Custom Action="CustomUninstallExec{{$i}}" After="{{if eq $i 0}}InstallInitialize{{else}}CustomUninstallExec{{dec $i}}{{end}}">REMOVE ~= "ALL"</Custom>
{{end}}
</InstallExecuteSequence>

<Feature Id="DefaultFeature" Level="1">
{{if gt (.Env.Vars | len) 0}}
<ComponentRef Id="ENVS" />
{{end}}
{{if gt (.Files.Items | len) 0}}
<ComponentRef Id="ApplicationFiles" />
{{end}}
{{if gt (.Shortcuts.Items | len) 0}}
<ComponentRef Id="ApplicationShortcuts" />
{{end}}
{{range $i, $e := .Directories}}
<ComponentGroupRef Id="AppFiles{{$i}}" />
{{end}}
</Feature>

<UI>
<!-- Define the installer UI -->
<UIRef Id="WixUI_HK" />
</UI>

<Property Id="WIXUI_INSTALLDIR" Value="INSTALLDIR" />

<!-- this should help to propagate env var changes -->
<CustomActionRef Id="WixBroadcastEnvironmentChange" />

</Product>

</Wix>
18 changes: 18 additions & 0 deletions uninstall.bat
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
@echo off
setlocal enabledelayedexpansion

set "SERVICE_NAME=harness-docker-runner-svc"

sc query "%SERVICE_NAME%" | find "STATE" | find /i "RUNNING" >nul
if %errorlevel% EQU 0 (
echo Service "%SERVICE_NAME%" is running.
echo Stopping service "%SERVICE_NAME%"...
sc.exe stop "%SERVICE_NAME%"
)

sc query "%SERVICE_NAME%" | find "STATE" | find /i "STOPPED" >nul
if %errorlevel% EQU 0 (
echo Service "%SERVICE_NAME%" is stopped.
echo Deleting service "%SERVICE_NAME%"...
sc.exe delete "%SERVICE_NAME%"
)
Loading

0 comments on commit 8c38321

Please sign in to comment.