Skip to content
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
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
docs/** linguist-documentation
*.iss linguist-vendored
61 changes: 60 additions & 1 deletion .github/workflows/pyinstaller.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -114,11 +114,70 @@ jobs:
run: |
cat win-version.txt

- name: "Build"
# BEGIN - Windows Installer

- name: "Windows Installer - Build"
if: ${{ matrix.os == 'windows-latest' }}
shell: bash
run: |
uvx toml-run pyinstaller -- ${{ matrix.extra-args }}

- name: "Windows Installer - Download PathMgr"
if: ${{ matrix.os == 'windows-latest' }}
uses: robinraju/release-downloader@daf26c55d821e836577a15f77d86ddc078948b05 # v1.12
with:
repository: "Bill-Stewart/PathMgr"
fileName: "PathMgr-2.0.0.zip"
out-file-path: "dist/PathMgr"
tag: "v2.0.0"
extract: true

- name: "Windows Installer - Inno Setup"
env:
version: ${{ inputs.version }}
shell: pwsh
run: |
echo "Building Version: $Env:version"
iscc.exe "/DMyAppVersion=$Env:version" installer.iss

- name: "Windows Installer - Debug Output"
if: ${{ matrix.os == 'windows-latest' }}
continue-on-error: true
shell: bash
run: |
echo "::group::dist"
ls -lAh dist/*
echo "::endgroup::"
echo "::group::out"
ls -lAhR out
echo "::endgroup::"

- name: "Windows Installer - Upload Artifact"
if: ${{ matrix.os == 'windows-latest' && github.event_name != 'release' }}
uses: actions/upload-artifact@v5
with:
name: windows-installer
path: out/*.exe

- name: "Windows Installer - Upload Release"
if: ${{ matrix.os == 'windows-latest' && github.event_name == 'release' }}
uses: cssnr/upload-release-action@latest
with:
globs: out/*.exe

- name: "Windows Installer - Cleanup"
if: ${{ matrix.os == 'windows-latest' }}
shell: bash
run: |
rm -rf dist out

# END - Windows Installer

- name: "Build"
shell: bash
run: |
uvx toml-run pyinstaller -- -F ${{ matrix.extra-args }}

- name: "List Artifacts"
continue-on-error: true
working-directory: dist
Expand Down
17 changes: 17 additions & 0 deletions .github/workflows/release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -162,3 +162,20 @@ jobs:
with:
webhook: ${{ secrets.DISCORD_WEBHOOK }}
description: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}

virustotal:
name: "VirusTotal Scan"
runs-on: ubuntu-latest
needs: [pyinstaller, release]
timeout-minutes: 5
if: ${{ github.event_name == 'release' }}

steps:
- name: "VirusTotal"
uses: cssnr/virustotal-action@master
continue-on-error: true
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
vt_api_key: ${{ secrets.VT_API_KEY }}
update_release: true
collapsed: true
9 changes: 5 additions & 4 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@
.idea/
*.iml
.vscode/
.*cache*
node_modules/
build/
dist/
out/
.venv/
venv/
__pycache__/
*.egg-info/
build/
dist/
.*cache/
*.log
*.pyc
.coverage
coverage.xml
Expand Down
Binary file added assets/post-install.rtf
Binary file not shown.
Binary file added assets/pre-install.rtf
Binary file not shown.
168 changes: 168 additions & 0 deletions installer.iss
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
#define MyAppName "ShareX CLI"
#define MyAppPublisher "CSSNR"
#define MyAppURL "https://cssnr.github.io/sharex-cli/"
#define MyAppExeName "sharex.exe"
#ifndef MyAppVersion
#define MyAppVersion "0.0.1"
#endif

[Setup]
AppId={{1FD9B94A-D2D2-40FA-81D5-A4B5BCD39A47}
AppName={#MyAppName}
AppVersion={#MyAppVersion}
AppVerName={#MyAppName} {#MyAppVersion}
AppPublisher={#MyAppPublisher}
AppPublisherURL={#MyAppURL}
AppSupportURL={#MyAppURL}
AppUpdatesURL={#MyAppURL}
;Compression=lzma
;SolidCompression=yes
DefaultDirName={autopf}\sharex-cli
DefaultGroupName={#MyAppName}
;DisableDirPage=yes
;DisableProgramGroupPage=yes
DisableFinishedPage=yes
InfoBeforeFile=assets\pre-install.rtf
InfoAfterFile=assets\post-install.rtf

OutputBaseFilename=windows-installer
OutputDir=out
PrivilegesRequired=lowest
PrivilegesRequiredOverridesAllowed=dialog
SetupIconFile=docs\favicon.ico
UninstallDisplayIcon={uninstallexe}
WizardStyle=modern dynamic

ChangesEnvironment=yes
;LicenseFile=LICENSE
;VersionInfoVersion={#MyAppVersion}

; "ArchitecturesAllowed=x64compatible" specifies that Setup cannot run
; on anything but x64 and Windows 11 on Arm.
;ArchitecturesAllowed=x64compatible
; "ArchitecturesInstallIn64BitMode=x64compatible" requests that the
; install be done in "64-bit mode" on x64 or Windows 11 on Arm,
; meaning it should use the native 64-bit Program Files directory and
; the 64-bit view of the registry.
ArchitecturesInstallIn64BitMode=x64compatible

[Languages]
Name: "english"; MessagesFile: "compiler:Default.isl"

[Files]
Source: "dist\PathMgr\i386\PathMgr.dll"; DestDir: "{app}"; Flags: uninsneveruninstall
;Source: "dist\{#MyAppExeName}"; DestDir: "{app}"; Flags: ignoreversion
Source: "dist\sharex\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs

[Icons]
Name: "{group}\{#MyAppName} Folder"; Filename: "{app}"
Name: "{group}\{#MyAppName} Documentation"; Filename: "{#MyAppURL}"
Name: "{group}\{cm:UninstallProgram,{#MyAppName}}"; Filename: "{uninstallexe}"

[Tasks]
Name: modifypath; Description: "&Add to Path"

[Code]
const
MODIFY_PATH_TASK_NAME = 'modifypath'; // Specify name of task

var
PathIsModified: Boolean; // Cache task selection from previous installs
ApplicationUninstalled: Boolean; // Has application been uninstalled?

// Import AddDirToPath() at setup time ('files:' prefix)
function DLLAddDirToPath(DirName: string; PathType, AddType: DWORD): DWORD;
external 'AddDirToPath@files:PathMgr.dll stdcall setuponly';

// Import RemoveDirFromPath() at uninstall time ('{app}\' prefix)
function DLLRemoveDirFromPath(DirName: string; PathType: DWORD): DWORD;
external 'RemoveDirFromPath@{app}\PathMgr.dll stdcall uninstallonly';

// Wrapper for AddDirToPath() DLL function
function AddDirToPath(const DirName: string): DWORD;
var
PathType, AddType: DWORD;
begin
// PathType = 0 - use system Path
// PathType = 1 - use user Path
// AddType = 0 - add to end of Path
// AddType = 1 - add to beginning of Path
if IsAdminInstallMode() then
PathType := 0
else
PathType := 1;
AddType := 0;
result := DLLAddDirToPath(DirName, PathType, AddType);
end;

// Wrapper for RemoveDirFromPath() DLL function
function RemoveDirFromPath(const DirName: string): DWORD;
var
PathType: DWORD;
begin
// PathType = 0 - use system Path
// PathType = 1 - use user Path
if IsAdminInstallMode() then
PathType := 0
else
PathType := 1;
result := DLLRemoveDirFromPath(DirName, PathType);
end;

procedure RegisterPreviousData(PreviousDataKey: Integer);
begin
// Store previous or current task selection as custom user setting
if PathIsModified or WizardIsTaskSelected(MODIFY_PATH_TASK_NAME) then
SetPreviousData(PreviousDataKey, MODIFY_PATH_TASK_NAME, 'true');
end;

function InitializeSetup(): Boolean;
begin
result := true;
// Was task selected during a previous install?
PathIsModified := GetPreviousData(MODIFY_PATH_TASK_NAME, '') = 'true';
end;

function InitializeUninstall(): Boolean;
begin
result := true;
// Was task selected during a previous install?
PathIsModified := GetPreviousData(MODIFY_PATH_TASK_NAME, '') = 'true';
ApplicationUninstalled := false;
end;

procedure CurStepChanged(CurStep: TSetupStep);
begin
if CurStep = ssPostInstall then
begin
// Add app directory to Path at post-install step if task selected
if PathIsModified or WizardIsTaskSelected(MODIFY_PATH_TASK_NAME) then
AddDirToPath(ExpandConstant('{app}'));
end;
end;

procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep);
begin
if CurUninstallStep = usUninstall then
begin
// Remove app directory from path during uninstall if task was selected;
// use variable because we can't use WizardIsTaskSelected() at uninstall
if PathIsModified then
RemoveDirFromPath(ExpandConstant('{app}'));
end
else if CurUninstallStep = usPostUninstall then
begin
ApplicationUninstalled := true;
end;
end;

procedure DeinitializeUninstall();
begin
if ApplicationUninstalled then
begin
// Unload and delete PathMgr.dll and remove app dir when uninstalling
UnloadDLL(ExpandConstant('{app}\PathMgr.dll'));
DeleteFile(ExpandConstant('{app}\PathMgr.dll'));
RemoveDir(ExpandConstant('{app}'));
end;
end;
8 changes: 7 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,13 @@ select = ["E4", "E7", "E9", "F", "B", "Q"]

[tool.scripts]
win-version = "uv run pyivf-make_version --source-format yaml --metadata-source .github/files/win-version.yaml --outfile win-version.txt"
pyinstaller = "uv run pyinstaller -F -n sharex -i docs/favicon.ico src/app.py"
pyinstaller = "uv run pyinstaller -n sharex -i docs/favicon.ico src/app.py"
pathmgr = [
"mkdir dist || echo dist dir exists",
"wget https://github.com/Bill-Stewart/PathMgr/releases/download/v2.0.0/PathMgr-2.0.0.zip -O dist/pathmgr.zip",
"unzip dist/pathmgr.zip -d dist/PathMgr",
]
inno = ["iscc.exe installer.iss"]
test = ["uv run coverage run -m pytest", "uv run coverage report -m"]
clean = "rm -rf .cache dist site"
build = "uv run hatch build"
Expand Down
Loading