Skip to content

Commit

Permalink
fix: binary execution mode compatibility (#406)
Browse files Browse the repository at this point in the history
* fix: fixing vanity address and init command issues with pyinstaller

* test: adding tests

* chore: refinements

* test: some test refinements

* chore: minor tweaks

* fix: fixing variable names

* fix: fixing based on PR comments

* test: fixing test

* test: add email env

* test: add --no-git to the tests

* chore: adding git identity prior to pytest in ci

* chore: testing ci

* chore: adding portability tests

* chore: testing ci

* chore: testing ci

* chore: testing ci

* chore: test ci

* chore: test

* chore: testing ci

* chore: test ci

* test: fixing test names-PR reviews

* docs: add docs about python_path usage in templates

* docs: change wordings

* chore: replacing init test to run against dummy template

* chore: addressing pr comments

* chore: testing ci

* chore: test

* chore: test

* chore: test

* chore: testing ci

* chore: testing ci

* chore: test

* chore: testing ci

* chore: minor refinements

* chore: minor tweaks

* fix: addressing pr comments

* test: fix a typo in test

* chore: fixing generator test for windows

* fix: PR comments

* docs: updating tutorial docs

---------

Co-authored-by: Altynbek Orumbayev <altynbek.orumbayev@makerx.com.au>
  • Loading branch information
negar-abbasi and aorumbayev authored Feb 8, 2024
1 parent 032cf85 commit 5cb9b1f
Show file tree
Hide file tree
Showing 21 changed files with 330 additions and 145 deletions.
47 changes: 33 additions & 14 deletions .github/actions/build-binaries/action.yaml
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
name: "Setup, Build, and Test"
description: "Set up Python with Poetry, build and test binaries"
name: "Setup, Build, and Test Pyinstaller Binaries"
description: "Build, test and upload binaries to GitHub releases and/or artifacts (ensure poetry dependencies are installed before running this action)"
inputs:
package_name:
description: "The name of the package to build and test"
required: true
upload_binaries:
production_release:
description: "Flag to determine if this is a production release"
required: true
operating_system:
Expand All @@ -24,41 +24,60 @@ runs:
run: ${{ inputs.build_command }}
shell: bash

- name: Test Executable
- name: Set TEST_CLI_PATH
run: |
ls -l dist
./dist/${{ inputs.package_name }}/${{ inputs.package_name }}${{ inputs.operating_system == 'windows-latest' && '.exe' || '' }} --help
TEST_CLI_PATH="${{ github.workspace }}/dist/${{ inputs.package_name }}/${{ inputs.package_name }}"
if [ "${{ inputs.operating_system }}" == "Windows" ]; then
TEST_CLI_PATH="${{ github.workspace }}\dist\${{ inputs.package_name }}\${{ inputs.package_name }}.exe"
fi
echo "TEST_CLI_PATH=$TEST_CLI_PATH" >> $GITHUB_ENV
shell: bash

- name: Run portability tests
run: |
echo "Executing: ${{ env.TEST_CLI_PATH }}"
git config --global user.email "actions@github.com" && git config --global user.name "github-actions"
poetry run pytest tests/ -m pyinstaller_binary_tests --cli_path "${{ env.TEST_CLI_PATH }}" --log-cli-level=INFO
shell: ${{ inputs.operating_system == 'Windows' && 'cmd' || 'bash' }}

- name: Set release version
shell: bash
continue-on-error: true
if: ${{ inputs.upload_binaries == 'true' }}
if: ${{ inputs.production_release == 'true' }}
run: |
echo "RELEASE_VERSION=$(git describe --tags $(git rev-list --tags --max-count=1))" >> $GITHUB_ENV
git describe --tags $(git rev-list --tags --max-count=1)
- name: Zip binaries
shell: bash
continue-on-error: true
if: ${{ inputs.upload_binaries == 'true' }}
run: |
ls -l dist
cd dist/algokit/
tar -zcvf ../../algokit-${{ env.RELEASE_VERSION }}-${{ inputs.operating_system }}-py${{ inputs.python_version }}.tar.gz *
if [ "${{ inputs.production_release }}" == "true" ]; then
tar -zcvf ../../algokit-${{ env.RELEASE_VERSION }}-${{ inputs.operating_system }}-py${{ inputs.python_version }}.tar.gz *
else
tar -zcvf ../../algokit-${{ inputs.operating_system }}-py${{ inputs.python_version }}.tar.gz *
fi
cd ../..
ls -l
- name: Upload binary as artifact
if: ${{ inputs.upload_binaries == 'true' }}
- name: Upload binary as artifact (release)
if: ${{ inputs.production_release == 'true' }}
uses: actions/upload-artifact@v4
with:
name: algokit-cli-${{ inputs.operating_system }}-py${{ inputs.python_version }}
name: algokit-${{ inputs.operating_system }}-py${{ inputs.python_version }}
path: algokit-${{ env.RELEASE_VERSION }}-${{ inputs.operating_system }}-py${{ inputs.python_version }}.tar.gz

- name: Upload binary as artifact (dev)
if: ${{ inputs.production_release != 'true' }}
uses: actions/upload-artifact@v4
with:
name: algokit-${{ inputs.operating_system }}-py${{ inputs.python_version }}
path: algokit-${{ inputs.operating_system }}-py${{ inputs.python_version }}.tar.gz

- name: Append binary to release
continue-on-error: true
if: ${{ inputs.upload_binaries == 'true' }}
if: ${{ inputs.production_release == 'true' }}
uses: softprops/action-gh-release@v1
with:
files: |
Expand Down
121 changes: 21 additions & 100 deletions .github/workflows/build-binaries.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,133 +3,54 @@ name: Build, Test and Publish Pyinstaller Binaries
on:
workflow_call:
inputs:
upload_binaries:
production_release:
required: true
type: string
python_version:
required: true
type: string

jobs:
build-binaries-ubuntu:
runs-on: ubuntu-latest
build-binaries:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
include:
- os: ubuntu-latest
build_command: "poetry run poe package_unix"
- os: windows-latest
build_command: "poetry run poe package_windows"
- os: macos-latest
build_command: "poetry run poe package_unix"
steps:
- name: Checkout source code (for release)
- name: Checkout source code
uses: actions/checkout@v4
if: ${{ inputs.upload_binaries == 'true' }}
with:
fetch-depth: 0

- name: Checkout source code (for build)
uses: actions/checkout@v4
if: ${{ inputs.upload_binaries != 'true' }}
with:
fetch-depth: 1

- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: ${{ inputs.python_version }}

- name: Set up Poetry
uses: ./.github/actions/setup-poetry

- uses: actions/cache@v4
name: Setup poetry cache
with:
path: ./.venv
key: venv-${{ hashFiles('poetry.lock') }}-${{ runner.os }}-${{ inputs.python_version }}

- name: Install dependencies
run: poetry install --no-interaction

- name: Build linux binary
uses: ./.github/actions/build-binaries
with:
python_version: ${{ inputs.python_version }}
package_name: "algokit"
upload_binaries: ${{ inputs.upload_binaries }}
operating_system: ${{ runner.os }}
build_command: "poetry run poe package_unix"

build-binaries-windows:
runs-on: windows-latest
steps:
- name: Checkout source code (for release)
uses: actions/checkout@v4
if: ${{ inputs.upload_binaries == 'true' }}
with:
fetch-depth: 0

- name: Checkout source code (for build)
uses: actions/checkout@v4
if: ${{ inputs.upload_binaries != 'true' }}
with:
fetch-depth: 1

- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: ${{ inputs.python_version }}

- name: Set up Poetry
uses: ./.github/actions/setup-poetry

- uses: actions/cache@v4
name: Setup poetry cache
with:
path: ./.venv
key: venv-${{ hashFiles('poetry.lock') }}-${{ runner.os }}-${{ inputs.python_version }}

- name: Install dependencies
run: poetry install --no-interaction

- name: Build windows binary
uses: ./.github/actions/build-binaries
with:
python_version: ${{ inputs.python_version }}
package_name: "algokit"
upload_binaries: ${{ inputs.upload_binaries }}
operating_system: ${{ runner.os }}
build_command: "poetry run poe package_windows"

build-binaries-macos:
runs-on: macos-latest
steps:
- name: Checkout source code (for release)
uses: actions/checkout@v4
if: ${{ inputs.upload_binaries == 'true' }}
with:
fetch-depth: 0

- name: Checkout source code (for build)
uses: actions/checkout@v4
if: ${{ inputs.upload_binaries != 'true' }}
with:
fetch-depth: 1
fetch-depth: ${{ inputs.production_release == 'true' && '0' || '1' }}

- name: Set up Python
uses: actions/setup-python@v4
uses: actions/setup-python@v5
with:
python-version: ${{ inputs.python_version }}

- name: Set up Poetry
uses: ./.github/actions/setup-poetry

- uses: actions/cache@v4
name: Setup poetry cache
- name: Setup poetry cache
uses: actions/cache@v4
with:
path: ./.venv
key: venv-${{ hashFiles('poetry.lock') }}-${{ runner.os }}-${{ inputs.python_version }}

- name: Install dependencies
run: poetry install --no-interaction

- name: Build macos binary
- name: Build & test binary
uses: ./.github/actions/build-binaries
with:
python_version: ${{ inputs.python_version }}
package_name: "algokit"
upload_binaries: ${{ inputs.upload_binaries }}
production_release: ${{ inputs.production_release }}
operating_system: ${{ runner.os }}
build_command: "poetry run poe package_unix"
build_command: ${{ matrix.build_command }}
4 changes: 3 additions & 1 deletion .github/workflows/build-python.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:
uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v4
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python }}

Expand All @@ -35,8 +35,10 @@ jobs:

- name: pytest + coverage
shell: bash
# git config is needed due to several tests relying on e2e copier invocation and copier relies on git during `copy` command
run: |
set -o pipefail
git config --global user.email "actions@github.com" && git config --global user.name "github-actions"
poetry run pytest -n auto --junitxml=pytest-junit.xml --cov-report=term-missing:skip-covered --cov=src | tee pytest-coverage.txt
id: pytest

Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/cd.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ jobs:
fetch-depth: 0

- name: Set up Python
uses: actions/setup-python@v4
uses: actions/setup-python@v5
with:
python-version: "3.10"

Expand Down Expand Up @@ -123,7 +123,7 @@ jobs:
uses: ./.github/workflows/build-binaries.yaml
needs: release
with:
upload_binaries: "true"
production_release: "true"
python_version: "3.12"

cd-publish-release-packages:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/check-python.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ jobs:
uses: actions/checkout@v4

- name: Set up Python 3.12
uses: actions/setup-python@v4
uses: actions/setup-python@v5
with:
python-version: "3.12"

Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/pr.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,14 @@ jobs:
uses: ./.github/workflows/check-python.yaml

pr-build:
name: Build and Test Python
name: Build & Test Python
needs: pr-check
uses: ./.github/workflows/build-python.yaml

pr-binaries-build:
name: Build Binaries
name: Build & Test Binaries
needs: pr-check
uses: ./.github/workflows/build-binaries.yaml
with:
upload_binaries: "false"
production_release: "false"
python_version: "3.12"
29 changes: 29 additions & 0 deletions docs/tutorials/algokit-template.md
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,35 @@ When creating an AlgoKit template, there are a few default behaviors that you ca

By combining predefined Copier answers with these default behaviors, you can create a smooth, efficient, and intuitive initialization experience for the users of your template.

### Executing Python Tasks in Templates

If you need to use Python scripts as tasks within your Copier templates, ensure that you have Python installed on the host machine.
By convention, AlgoKit automatically detects the Python installation on your machine and fills in the `python_path` variable accordingly.
This process ensures that any Python scripts included as tasks within your Copier templates will execute using the system's Python interpreter.
It's important to note that the use of `_copier_python` is not recommended. Here's an example of specifying a Python script execution in your `copier.yaml` without needing to explicitly use `_copier_python`:

```yaml
- "{{ python_path }} your_python_script.py"
```

If you'd like your template to be backwards compatible with versions of `algokit-cli` older than `v1.11.3` when executing custom python scripts via `copier` tasks, you can use a conditional statement to determine the Python path:

```yaml
- "{{ python_path if python_path else _copier_python }} your_python_script.py"
# _copier_python above is used for backwards compatibility with versions < v1.11.3 of the algokit cli
```

And to define `python_path` in your Copier questions:

```yaml
# Auto determined by algokit-cli from v1.11.3 to allow execution of python script
# in binary mode.
python_path:
type: str
help: Path to the sys.executable.
when: false
```

### Working with Generators

After mastering the use of `copier` and building your templates based on the official AlgoKit template repositories, you can enhance your proficiency by learning to define `custom generators`. Essentially, generators are smaller-scope `copier` templates designed to provide additional functionality after a project has been initialized from the template.
Expand Down
Loading

1 comment on commit 5cb9b1f

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Coverage

Coverage Report
FileStmtsMissCoverMissing
src/algokit
   __init__.py15753%6–13, 17–24, 32–34
   __main__.py440%1–7
src/algokit/cli
   completions.py108298%83, 98
   deploy.py72790%44, 46, 92–94, 158, 182
   dispenser.py121199%77
   doctor.py48394%142–144
   explore.py501276%34–39, 41–46
   generate.py67396%74–75, 140
   goal.py44198%71
   init.py1951692%284–285, 335, 338–340, 351, 395, 421, 461, 470–472, 475–480, 493
   localnet.py1191587%74–78, 111, 123, 138–148, 161, 206, 227–228
   task.py34391%25–28
src/algokit/cli/common
   utils.py26292%120, 123
src/algokit/cli/tasks
   analyze.py81199%81
   assets.py821384%65–66, 72, 74–75, 105, 119, 125–126, 132, 134, 136–137
   ipfs.py51884%52, 80, 92, 94–95, 105–107
   mint.py66494%48, 70, 91, 250
   send_transaction.py651085%52–53, 57, 89, 158, 170–174
   sign_transaction.py59886%21, 28–30, 71–72, 109, 123
   transfer.py39392%26, 90, 117
   utils.py994555%26–34, 40–43, 75–76, 100–101, 125–133, 152–162, 209, 258–259, 279–290, 297–299
   vanity_address.py561082%41, 45–48, 112, 114, 121–123
   wallet.py79495%21, 66, 136, 162
src/algokit/core
   bootstrap.py1171091%101–102, 124, 151, 180–185
   conf.py54885%12, 24, 28, 36, 38, 71–73
   deploy.py691184%61–64, 73–75, 79, 84, 91–93
   dispenser.py2022687%91, 123–124, 141–149, 191–192, 198–200, 218–219, 259–260, 318, 332–334, 345–346, 356, 369, 384
   doctor.py65789%67–69, 92–94, 134
   generate.py48394%44, 81, 99
   goal.py60395%30–31, 41
   log_handlers.py68790%50–51, 63, 112–116, 125
   proc.py45198%98
   sandbox.py2181892%62, 73–75, 96, 142–149, 160, 456, 472, 497, 505
   typed_client_generation.py80594%55–57, 70, 75
   utils.py1043170%44–45, 49–68, 129, 132, 138–152
   version_prompt.py72889%26–27, 39, 58–61, 79, 108
src/algokit/core/tasks
   analyze.py94397%106–113, 188
   ipfs.py63789%58–64, 140, 144, 146, 152
   nfd.py491373%25, 31, 34–41, 70–72, 99–101
   vanity_address.py903462%49–50, 54, 59–75, 92–108, 128–131
   wallet.py71593%37, 129, 155–157
src/algokit/core/tasks/mint
   mint.py781087%123–133, 187
   models.py901188%50, 52, 57, 71–74, 85–88
TOTAL348740388% 

Tests Skipped Failures Errors Time
402 0 💤 0 ❌ 0 🔥 22.902s ⏱️

Please sign in to comment.