Add Inno Setup installers and build step
Add Inno Setup compilation to the Windows CI: the workflow now installs Inno Setup via choco, adjusts PATH, and runs iscc to compile two installers (standard and -ffmpeg) using /DMyAppVersion,/DMyAppExeName and /DSourceDir, placing outputs into repo/artifacts and failing the job on non-zero exit. Also add two new Inno Setup scripts in setup-scripts/: Setup-windows.iss and Setup-windows-ffmpeg.iss. The scripts include metadata, multi-language support, file/icon/registry/run entries, and Pascal code to create or update the user's ytsage_config.json language setting; the -ffmpeg script adds an optional task to append the app folder to the user's PATH.
This commit is contained in:
@@ -449,6 +449,39 @@ jobs:
|
||||
Write-Host " Artifacts directory not found!"
|
||||
}
|
||||
|
||||
- name: Create Installer (Inno Setup)
|
||||
shell: powershell
|
||||
run: |
|
||||
$version = "${{ steps.get_version.outputs.VERSION }}"
|
||||
|
||||
# Install Inno Setup
|
||||
choco install innosetup --no-progress
|
||||
|
||||
# Add matches generally C:\Program Files (x86)\Inno Setup 6
|
||||
$env:Path = "C:\Program Files (x86)\Inno Setup 6;$env:Path"
|
||||
|
||||
# Compile
|
||||
$exeName = "YTSage-v$version.exe"
|
||||
Write-Host "Compiling installer for $exeName..."
|
||||
|
||||
# Note: Setup-windows.iss is in setup-scripts/
|
||||
# OutputDir is ..\artifacts (relative to script) -> repo/artifacts
|
||||
# SourceDir is ..\dist\YTSage (relative to script) -> repo/dist/YTSage
|
||||
|
||||
iscc /DMyAppVersion="$version" /DMyAppExeName="$exeName" /DSourceDir="..\dist\YTSage" "setup-scripts\Setup-windows.iss"
|
||||
|
||||
# Compile FFmpeg Installer
|
||||
$exeNameFFmpeg = "YTSage-v$version-ffmpeg.exe"
|
||||
Write-Host "Compiling FFmpeg installer for $exeNameFFmpeg..."
|
||||
iscc /DMyAppVersion="$version" /DMyAppExeName="$exeNameFFmpeg" /DSourceDir="..\dist\YTSage-FFmpeg" "setup-scripts\Setup-windows-ffmpeg.iss"
|
||||
|
||||
if ($LASTEXITCODE -eq 0) {
|
||||
Write-Host "Installer compilation successful."
|
||||
} else {
|
||||
Write-Host "Installer compilation failed."
|
||||
exit 1
|
||||
}
|
||||
|
||||
- name: Create draft release
|
||||
uses: softprops/action-gh-release@v2
|
||||
with:
|
||||
|
||||
@@ -0,0 +1,151 @@
|
||||
; Script generated by the Inno Setup Script Wizard.
|
||||
|
||||
#define MyAppName "YTSage"
|
||||
#ifndef MyAppVersion
|
||||
#define MyAppVersion "0.0.0"
|
||||
#endif
|
||||
#define MyAppPublisher "oop7"
|
||||
#define MyAppURL "https://github.com/oop7/YTSage/"
|
||||
#ifndef MyAppExeName
|
||||
#define MyAppExeName "YTSage-ffmpeg.exe"
|
||||
#endif
|
||||
#ifndef SourceDir
|
||||
#define SourceDir "..\dist\YTSage-FFmpeg"
|
||||
#endif
|
||||
|
||||
[Setup]
|
||||
AppId={{56997322-2A3A-4338-AEF1-C3C8BB28AC4F}
|
||||
AppName={#MyAppName}
|
||||
AppVersion={#MyAppVersion}
|
||||
AppPublisher={#MyAppPublisher}
|
||||
AppPublisherURL={#MyAppURL}
|
||||
AppSupportURL={#MyAppURL}
|
||||
AppUpdatesURL={#MyAppURL}
|
||||
DefaultDirName={autopf}\{#MyAppName}
|
||||
UninstallDisplayIcon={app}\{#MyAppExeName}
|
||||
ArchitecturesAllowed=x64compatible
|
||||
ArchitecturesInstallIn64BitMode=x64compatible
|
||||
DisableProgramGroupPage=yes
|
||||
LicenseFile=..\LICENSE
|
||||
PrivilegesRequired=lowest
|
||||
PrivilegesRequiredOverridesAllowed=dialog
|
||||
OutputBaseFilename=YTSage-v{#MyAppVersion}-ffmpeg-Setup
|
||||
SolidCompression=yes
|
||||
WizardStyle=modern
|
||||
OutputDir=..\artifacts
|
||||
|
||||
[Languages]
|
||||
Name: "english"; MessagesFile: "compiler:Default.isl"
|
||||
Name: "arabic"; MessagesFile: "compiler:Languages\Arabic.isl"
|
||||
Name: "brazilianportuguese"; MessagesFile: "compiler:Languages\BrazilianPortuguese.isl"
|
||||
Name: "french"; MessagesFile: "compiler:Languages\French.isl"
|
||||
Name: "german"; MessagesFile: "compiler:Languages\German.isl"
|
||||
Name: "italian"; MessagesFile: "compiler:Languages\Italian.isl"
|
||||
Name: "japanese"; MessagesFile: "compiler:Languages\Japanese.isl"
|
||||
Name: "polish"; MessagesFile: "compiler:Languages\Polish.isl"
|
||||
Name: "portuguese"; MessagesFile: "compiler:Languages\Portuguese.isl"
|
||||
Name: "russian"; MessagesFile: "compiler:Languages\Russian.isl"
|
||||
Name: "spanish"; MessagesFile: "compiler:Languages\Spanish.isl"
|
||||
Name: "turkish"; MessagesFile: "compiler:Languages\Turkish.isl"
|
||||
|
||||
[Tasks]
|
||||
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}";
|
||||
Name: "addtopath"; Description: "Add ffmpeg to user PATH environment variable"; GroupDescription: "Additional options:"; Flags: unchecked
|
||||
|
||||
[Files]
|
||||
Source: "{#SourceDir}\{#MyAppExeName}"; DestDir: "{app}"; Flags: ignoreversion
|
||||
Source: "{#SourceDir}\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
|
||||
|
||||
[Icons]
|
||||
Name: "{autoprograms}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"
|
||||
Name: "{autodesktop}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: desktopicon
|
||||
|
||||
[Registry]
|
||||
Root: HKCU; Subkey: "Environment"; ValueType: expandsz; ValueName: "Path"; ValueData: "{olddata};{app}"; Tasks: addtopath; Check: NeedsAddPath('{app}')
|
||||
|
||||
[Run]
|
||||
Filename: "{app}\{#MyAppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(MyAppName, '&', '&&')}}"; Flags: nowait postinstall skipifsilent
|
||||
|
||||
[Code]
|
||||
function NeedsAddPath(Param: string): boolean;
|
||||
var
|
||||
OrigPath: string;
|
||||
ParamExpanded: string;
|
||||
begin
|
||||
// Expand the setup constants like {app} from Param
|
||||
ParamExpanded := ExpandConstant(Param);
|
||||
if not RegQueryStringValue(HKEY_CURRENT_USER, 'Environment', 'Path', OrigPath) then
|
||||
begin
|
||||
Result := True;
|
||||
exit;
|
||||
end;
|
||||
// Look for the path with leading and trailing semicolon
|
||||
Result := Pos(';' + UpperCase(ParamExpanded) + ';', ';' + UpperCase(OrigPath) + ';') = 0;
|
||||
if Result = True then
|
||||
Result := Pos(';' + UpperCase(ParamExpanded) + '\;', ';' + UpperCase(OrigPath) + ';') = 0;
|
||||
end;
|
||||
|
||||
procedure UpdateLanguageConfig;
|
||||
var
|
||||
LanguageCode: string;
|
||||
ConfigPath: string;
|
||||
FileContent: AnsiString;
|
||||
JsonContent: string;
|
||||
LangPattern: string;
|
||||
P_Start, P_End: Integer;
|
||||
begin
|
||||
if ActiveLanguage = 'english' then LanguageCode := 'en'
|
||||
else if ActiveLanguage = 'arabic' then LanguageCode := 'ar'
|
||||
else if ActiveLanguage = 'brazilianportuguese' then LanguageCode := 'pt-br'
|
||||
else if ActiveLanguage = 'french' then LanguageCode := 'fr'
|
||||
else if ActiveLanguage = 'german' then LanguageCode := 'de'
|
||||
else if ActiveLanguage = 'italian' then LanguageCode := 'it'
|
||||
else if ActiveLanguage = 'japanese' then LanguageCode := 'ja'
|
||||
else if ActiveLanguage = 'polish' then LanguageCode := 'pl'
|
||||
else if ActiveLanguage = 'portuguese' then LanguageCode := 'pt'
|
||||
else if ActiveLanguage = 'russian' then LanguageCode := 'ru'
|
||||
else if ActiveLanguage = 'spanish' then LanguageCode := 'es'
|
||||
else if ActiveLanguage = 'turkish' then LanguageCode := 'tr'
|
||||
else LanguageCode := 'en';
|
||||
|
||||
ConfigPath := ExpandConstant('{localappdata}\YTSage\data\ytsage_config.json');
|
||||
|
||||
if not DirExists(ExtractFilePath(ConfigPath)) then
|
||||
ForceDirectories(ExtractFilePath(ConfigPath));
|
||||
|
||||
if FileExists(ConfigPath) then
|
||||
begin
|
||||
if LoadStringFromFile(ConfigPath, FileContent) then
|
||||
begin
|
||||
JsonContent := String(FileContent);
|
||||
LangPattern := '"language": "';
|
||||
P_Start := Pos(LangPattern, JsonContent);
|
||||
if P_Start > 0 then
|
||||
begin
|
||||
P_Start := P_Start + Length(LangPattern);
|
||||
P_End := Pos('"', Copy(JsonContent, P_Start, Length(JsonContent)));
|
||||
if P_End > 0 then
|
||||
begin
|
||||
Delete(JsonContent, P_Start, P_End - 1);
|
||||
Insert(LanguageCode, JsonContent, P_Start);
|
||||
SaveStringToFile(ConfigPath, AnsiString(JsonContent), False);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end
|
||||
else
|
||||
begin
|
||||
JsonContent := '{' + #13#10 +
|
||||
' "language": "' + LanguageCode + '"' + #13#10 +
|
||||
'}';
|
||||
SaveStringToFile(ConfigPath, AnsiString(JsonContent), False);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure CurStepChanged(CurStep: TSetupStep);
|
||||
begin
|
||||
if CurStep = ssPostInstall then
|
||||
begin
|
||||
UpdateLanguageConfig();
|
||||
end;
|
||||
end;
|
||||
@@ -0,0 +1,129 @@
|
||||
; Script generated by the Inno Setup Script Wizard.
|
||||
|
||||
#define MyAppName "YTSage"
|
||||
#ifndef MyAppVersion
|
||||
#define MyAppVersion "0.0.0"
|
||||
#endif
|
||||
#define MyAppPublisher "oop7"
|
||||
#define MyAppURL "https://github.com/oop7/YTSage/"
|
||||
#ifndef MyAppExeName
|
||||
#define MyAppExeName "YTSage.exe"
|
||||
#endif
|
||||
#ifndef SourceDir
|
||||
#define SourceDir "..\dist\YTSage"
|
||||
#endif
|
||||
|
||||
[Setup]
|
||||
AppId={{AE618DBF-DD56-462D-9C09-2C2B7A41B201}
|
||||
AppName={#MyAppName}
|
||||
AppVersion={#MyAppVersion}
|
||||
AppPublisher={#MyAppPublisher}
|
||||
AppPublisherURL={#MyAppURL}
|
||||
AppSupportURL={#MyAppURL}
|
||||
AppUpdatesURL={#MyAppURL}
|
||||
DefaultDirName={autopf}\{#MyAppName}
|
||||
UninstallDisplayIcon={app}\{#MyAppExeName}
|
||||
ArchitecturesAllowed=x64compatible
|
||||
ArchitecturesInstallIn64BitMode=x64compatible
|
||||
DisableProgramGroupPage=yes
|
||||
LicenseFile=..\LICENSE
|
||||
PrivilegesRequired=lowest
|
||||
PrivilegesRequiredOverridesAllowed=dialog
|
||||
OutputBaseFilename=YTSage-v{#MyAppVersion}-Setup
|
||||
SolidCompression=yes
|
||||
WizardStyle=modern
|
||||
OutputDir=..\artifacts
|
||||
|
||||
[Languages]
|
||||
Name: "english"; MessagesFile: "compiler:Default.isl"
|
||||
Name: "arabic"; MessagesFile: "compiler:Languages\Arabic.isl"
|
||||
Name: "brazilianportuguese"; MessagesFile: "compiler:Languages\BrazilianPortuguese.isl"
|
||||
Name: "french"; MessagesFile: "compiler:Languages\French.isl"
|
||||
Name: "german"; MessagesFile: "compiler:Languages\German.isl"
|
||||
Name: "italian"; MessagesFile: "compiler:Languages\Italian.isl"
|
||||
Name: "japanese"; MessagesFile: "compiler:Languages\Japanese.isl"
|
||||
Name: "polish"; MessagesFile: "compiler:Languages\Polish.isl"
|
||||
Name: "portuguese"; MessagesFile: "compiler:Languages\Portuguese.isl"
|
||||
Name: "russian"; MessagesFile: "compiler:Languages\Russian.isl"
|
||||
Name: "spanish"; MessagesFile: "compiler:Languages\Spanish.isl"
|
||||
Name: "turkish"; MessagesFile: "compiler:Languages\Turkish.isl"
|
||||
|
||||
[Tasks]
|
||||
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}";
|
||||
|
||||
[Files]
|
||||
Source: "{#SourceDir}\{#MyAppExeName}"; DestDir: "{app}"; Flags: ignoreversion
|
||||
Source: "{#SourceDir}\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
|
||||
|
||||
[Icons]
|
||||
Name: "{autoprograms}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"
|
||||
Name: "{autodesktop}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: desktopicon
|
||||
|
||||
[Run]
|
||||
Filename: "{app}\{#MyAppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(MyAppName, '&', '&&')}}"; Flags: nowait postinstall skipifsilent
|
||||
|
||||
[Code]
|
||||
procedure UpdateLanguageConfig;
|
||||
var
|
||||
LanguageCode: string;
|
||||
ConfigPath: string;
|
||||
FileContent: AnsiString;
|
||||
JsonContent: string;
|
||||
LangPattern: string;
|
||||
P_Start, P_End: Integer;
|
||||
begin
|
||||
if ActiveLanguage = 'english' then LanguageCode := 'en'
|
||||
else if ActiveLanguage = 'arabic' then LanguageCode := 'ar'
|
||||
else if ActiveLanguage = 'brazilianportuguese' then LanguageCode := 'pt-br'
|
||||
else if ActiveLanguage = 'french' then LanguageCode := 'fr'
|
||||
else if ActiveLanguage = 'german' then LanguageCode := 'de'
|
||||
else if ActiveLanguage = 'italian' then LanguageCode := 'it'
|
||||
else if ActiveLanguage = 'japanese' then LanguageCode := 'ja'
|
||||
else if ActiveLanguage = 'polish' then LanguageCode := 'pl'
|
||||
else if ActiveLanguage = 'portuguese' then LanguageCode := 'pt'
|
||||
else if ActiveLanguage = 'russian' then LanguageCode := 'ru'
|
||||
else if ActiveLanguage = 'spanish' then LanguageCode := 'es'
|
||||
else if ActiveLanguage = 'turkish' then LanguageCode := 'tr'
|
||||
else LanguageCode := 'en';
|
||||
|
||||
ConfigPath := ExpandConstant('{localappdata}\YTSage\data\ytsage_config.json');
|
||||
|
||||
if not DirExists(ExtractFilePath(ConfigPath)) then
|
||||
ForceDirectories(ExtractFilePath(ConfigPath));
|
||||
|
||||
if FileExists(ConfigPath) then
|
||||
begin
|
||||
if LoadStringFromFile(ConfigPath, FileContent) then
|
||||
begin
|
||||
JsonContent := String(FileContent);
|
||||
LangPattern := '"language": "';
|
||||
P_Start := Pos(LangPattern, JsonContent);
|
||||
if P_Start > 0 then
|
||||
begin
|
||||
P_Start := P_Start + Length(LangPattern);
|
||||
P_End := Pos('"', Copy(JsonContent, P_Start, Length(JsonContent)));
|
||||
if P_End > 0 then
|
||||
begin
|
||||
Delete(JsonContent, P_Start, P_End - 1);
|
||||
Insert(LanguageCode, JsonContent, P_Start);
|
||||
SaveStringToFile(ConfigPath, AnsiString(JsonContent), False);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end
|
||||
else
|
||||
begin
|
||||
JsonContent := '{' + #13#10 +
|
||||
' "language": "' + LanguageCode + '"' + #13#10 +
|
||||
'}';
|
||||
SaveStringToFile(ConfigPath, AnsiString(JsonContent), False);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure CurStepChanged(CurStep: TSetupStep);
|
||||
begin
|
||||
if CurStep = ssPostInstall then
|
||||
begin
|
||||
UpdateLanguageConfig();
|
||||
end;
|
||||
end;
|
||||
Reference in New Issue
Block a user