Skip to content
Open
157 changes: 157 additions & 0 deletions .github/workflows/1-1
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
name: Versatile PyInstaller
author: '@sayyid5416'
description: Customisable GitHub Action to package python scripts into executables for different OS's
branding:
icon: hard-drive
color: yellow


inputs:
spec:
description: >
path of your '.py' or '.spec' file.
- This file will be used to create executable.
- If .py: Generated spec file will also be uploaded as artifact
required: true
default: ''
requirements:
description: path of your requirements.txt file
default: ''
options:
description: >
Options to set for pyinstaller command
Ex: options: '--onedir, -F' (seperated by comma and space)
- Supported options: Check readme
default: ''
spec_options:
description: >
Custom parameters for spec file. (won't work with .py spec file)
Ex: spec_options: '--debug'
default: ''
python_ver:
description: specific python version you want to use
default: '3.10'
python_arch:
description: specific python architecture you want to use
default: 'x64'
pyinstaller_ver:
description: specific pyinstaller version you want to use
default: ''
exe_path:
description: Path on runner-os, where generated executable files are stored
default: './dist'
upload_exe_with_name:
description: If passed, uploads executable artifact with this name. Else, artifact won't be uploaded.
default: ''
clean_checkout:
description: 'If true, perform a clean checkout; if false, skip cleaning. Cleaning will remove all existing local files not in the repository during checkout. If you use utilities like pyinstaller-versionfile, set this to false.'
default: true
lfs:
description: Whether to download Git-LFS files (passed to actions/checkout)
default: false
compression_level:
description: 'Level of compression for archive (between 0 and 9). 0 = No compression, 9 = Max compression.'
default: 6


outputs:
executable_path:
description: path on runner-os, where generated executable files are stored
value: ${{ inputs.exe_path }}
is_uploaded:
description: true, if packaged executable has been uploaded as artifact
value: ${{ steps.exe_uploading.outputs.uploaded }}



runs:
using: 'composite'
steps:

- name: (Install) python
uses: actions/setup-python@v5
with:
python-version: ${{ inputs.python_ver }}
architecture: ${{ inputs.python_arch }}

- name: (Install) python dev tools
shell: bash
run: python -m pip install pip wheel setuptools

- name: checks for inputs
shell: bash
run: python "${{ github.action_path }}/src/checks.py"
env:
spec: ${{ inputs.spec }}
upload_exe_with_name: ${{ inputs.upload_exe_with_name }}

- name: (Set) modified outputs
id: mods
shell: bash
run: python "${{ github.action_path }}/src/mods.py"
env:
spec: ${{ inputs.spec }}
options: ${{ inputs.options }}
spec_options: ${{ inputs.spec_options }}

- name: Checkout repository
uses: actions/checkout@v4
with:
clean: ${{ inputs.clean_checkout }}
lfs: ${{ inputs.lfs }}

- name: (Install) dependencies
if: inputs.requirements != ''
run: python -m pip install -r "${{ inputs.requirements }}"
shell: bash

- name: (Install) pyinstaller
shell: bash
run: pip install pyinstaller${{ inputs.pyinstaller_ver }}

- name: (Create) Executable
shell: bash
run: |
pyinstaller \
--clean \
--noconfirm \
--dist ${{ inputs.exe_path }} \
${{ steps.mods.outputs.supported_options }} \
"${{ inputs.spec }}" \
${{ steps.mods.outputs.supported_spec_options }}

echo "✔️ Executable created successfully at _'${{ inputs.exe_path }}'_" >> $GITHUB_STEP_SUMMARY
echo " - Python version used: '${{ inputs.python_ver }}'" >> $GITHUB_STEP_SUMMARY
echo " - Python architecture used: '${{ inputs.python_arch }}'" >> $GITHUB_STEP_SUMMARY

- name: (Upload) Executable
id: artifact_upload
if: inputs.upload_exe_with_name != ''
uses: actions/upload-artifact@v4
with:
name: ${{ inputs.upload_exe_with_name }}
path: ${{ inputs.exe_path }}
compression-level: ${{ inputs.compression_level }}

- name: (Upload) generated spec file - if .py
if: endsWith(inputs.spec, '.py')
uses: actions/upload-artifact@v4
with:
name: Generated spec file for ${{ inputs.upload_exe_with_name }}
path: ${{ steps.mods.outputs.spec_path }}

- name: If executable upload success
id: exe_uploading
if: steps.artifact_upload.conclusion == 'success'
shell: bash
run: |
echo "✔️ Executable **_(${{ inputs.upload_exe_with_name }})_** uploaded successfully" >> $GITHUB_STEP_SUMMARY
echo "uploaded='true'" >> $GITHUB_OUTPUT

- name: If executable upload fails
if: failure() && steps.artifact_upload.conclusion == 'failure'
shell: bash
run: |
echo "::warning title=Failed-Upload::\
Executable couldn't upload. \
Check available storage at: 'settings > billing > Storage for Actions and Packages'."
157 changes: 157 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
name: Versatile PyInstaller
author: '@sayyid5416'
description: Customisable GitHub Action to package python scripts into executables for different OS's
branding:
icon: hard-drive
color: yellow


inputs:
spec:
description: >
path of your '.py' or '.spec' file.
- This file will be used to create executable.
- If .py: Generated spec file will also be uploaded as artifact
required: true
default: ''
requirements:
description: path of your requirements.txt file
default: ''
options:
description: >
Options to set for pyinstaller command
Ex: options: '--onedir, -F' (seperated by comma and space)
- Supported options: Check readme
default: ''
spec_options:
description: >
Custom parameters for spec file. (won't work with .py spec file)
Ex: spec_options: '--debug'
default: ''
python_ver:
description: specific python version you want to use
default: '3.10'
python_arch:
description: specific python architecture you want to use
default: 'x64'
pyinstaller_ver:
description: specific pyinstaller version you want to use
default: ''
exe_path:
description: Path on runner-os, where generated executable files are stored
default: './dist'
upload_exe_with_name:
description: If passed, uploads executable artifact with this name. Else, artifact won't be uploaded.
default: ''
clean_checkout:
description: 'If true, perform a clean checkout; if false, skip cleaning. Cleaning will remove all existing local files not in the repository during checkout. If you use utilities like pyinstaller-versionfile, set this to false.'
default: true
lfs:
description: Whether to download Git-LFS files (passed to actions/checkout)
default: false
compression_level:
description: 'Level of compression for archive (between 0 and 9). 0 = No compression, 9 = Max compression.'
default: 6


outputs:
executable_path:
description: path on runner-os, where generated executable files are stored
value: ${{ inputs.exe_path }}
is_uploaded:
description: true, if packaged executable has been uploaded as artifact
value: ${{ steps.exe_uploading.outputs.uploaded }}



runs:
using: 'composite'
steps:

- name: (Install) python
uses: actions/setup-python@v5
with:
python-version: ${{ inputs.python_ver }}
architecture: ${{ inputs.python_arch }}

- name: (Install) python dev tools
shell: bash
run: python -m pip install pip wheel setuptools

- name: checks for inputs
shell: bash
run: python "${{ github.action_path }}/src/checks.py"
env:
spec: ${{ inputs.spec }}
upload_exe_with_name: ${{ inputs.upload_exe_with_name }}

- name: (Set) modified outputs
id: mods
shell: bash
run: python "${{ github.action_path }}/src/mods.py"
env:
spec: ${{ inputs.spec }}
options: ${{ inputs.options }}
spec_options: ${{ inputs.spec_options }}

- name: Checkout repository
uses: actions/checkout@v4
with:
clean: ${{ inputs.clean_checkout }}
lfs: ${{ inputs.lfs }}

- name: (Install) dependencies
if: inputs.requirements != ''
run: python -m pip install -r "${{ inputs.requirements }}"
shell: bash

- name: (Install) pyinstaller
shell: bash
run: pip install pyinstaller${{ inputs.pyinstaller_ver }}

- name: (Create) Executable
shell: bash
run: |
pyinstaller \
--clean \
--noconfirm \
--dist ${{ inputs.exe_path }} \
${{ steps.mods.outputs.supported_options }} \
"${{ inputs.spec }}" \
${{ steps.mods.outputs.supported_spec_options }}

echo "✔️ Executable created successfully at _'${{ inputs.exe_path }}'_" >> $GITHUB_STEP_SUMMARY
echo " - Python version used: '${{ inputs.python_ver }}'" >> $GITHUB_STEP_SUMMARY
echo " - Python architecture used: '${{ inputs.python_arch }}'" >> $GITHUB_STEP_SUMMARY

- name: (Upload) Executable
id: artifact_upload
if: inputs.upload_exe_with_name != ''
uses: actions/upload-artifact@v4
with:
name: ${{ inputs.upload_exe_with_name }}
path: ${{ inputs.exe_path }}
compression-level: ${{ inputs.compression_level }}

- name: (Upload) generated spec file - if .py
if: endsWith(inputs.spec, '.py')
uses: actions/upload-artifact@v4
with:
name: Generated spec file for ${{ inputs.upload_exe_with_name }}
path: ${{ steps.mods.outputs.spec_path }}

- name: If executable upload success
id: exe_uploading
if: steps.artifact_upload.conclusion == 'success'
shell: bash
run: |
echo "✔️ Executable **_(${{ inputs.upload_exe_with_name }})_** uploaded successfully" >> $GITHUB_STEP_SUMMARY
echo "uploaded='true'" >> $GITHUB_OUTPUT

- name: If executable upload fails
if: failure() && steps.artifact_upload.conclusion == 'failure'
shell: bash
run: |
echo "::warning title=Failed-Upload::\
Executable couldn't upload. \
Check available storage at: 'settings > billing > Storage for Actions and Packages'."
Loading