From 842c072751eb946b08c51ccc63d6d3501142680a Mon Sep 17 00:00:00 2001
From: David Rojas
Date: Wed, 13 Nov 2024 18:31:16 -0500
Subject: [PATCH 1/5] Added task to copier to warn that template is deprecated
and updated README
---
README.md | 4 ++++
copier.yaml | 4 ++++
2 files changed, 8 insertions(+)
diff --git a/README.md b/README.md
index befc3ec..9dff1d9 100644
--- a/README.md
+++ b/README.md
@@ -9,6 +9,10 @@
+---
+# DEPRECATED
+This template has been deprecated. Beaker for Algorand Smart Contract development is no longer supported. Please use Algorand Python instead. The Algorand Python template can be found at https://github.com/algorandfoundation/algokit-python-template.
+
---
This template provides a production-ready baseline for developing and deploying [Beaker](https://github.com/algorand-devrel/beaker) smart contracts.
diff --git a/copier.yaml b/copier.yaml
index d9f7c11..0d1d637 100644
--- a/copier.yaml
+++ b/copier.yaml
@@ -1,6 +1,10 @@
_subdirectory: template_content
_templates_suffix: ".jinja"
+_tasks:
+ - "python -c \"print('WARNING: This template has been deprecated. Beaker for Algorand Smart Contract development is no longer supported.\\nPlease use Algorand Python instead. The Algorand Python template can be found at https://github.com/algorandfoundation/algokit-python-template')\""
+ - "python -c \"exit(1)\""
+
use_workspace:
type: bool
when: false # never prompted to user explicitly, instead expect cli to auto fill (supported cli versions > v1.13.x)
From 375b54f6d4099d495fafbd7d8cfa8e06ea36eb58 Mon Sep 17 00:00:00 2001
From: David Rojas
Date: Mon, 18 Nov 2024 16:06:09 -0500
Subject: [PATCH 2/5] chore: deprecated tests and created a test for a failed
init
---
tests/test_generators.py | 16 ++++++++++++++++
tests/test_templates.py | 1 +
2 files changed, 17 insertions(+)
diff --git a/tests/test_generators.py b/tests/test_generators.py
index bb503bb..fd08ceb 100644
--- a/tests/test_generators.py
+++ b/tests/test_generators.py
@@ -176,6 +176,7 @@ def run_generator(
@pytest.mark.parametrize("language", ["python", "typescript"])
+@pytest.mark.skip(reason="This test is deprecated since the template is deprecated")
def test_smart_contract_generator_default_starter_preset(
language: str, working_dir: Path
) -> None:
@@ -207,6 +208,7 @@ def test_smart_contract_generator_default_starter_preset(
@pytest.mark.parametrize("language", ["python", "typescript"])
+@pytest.mark.skip(reason="This test is deprecated since the template is deprecated")
def test_smart_contract_generator_default_production_preset(
language: str, working_dir: Path
) -> None:
@@ -235,3 +237,17 @@ def test_smart_contract_generator_default_production_preset(
response = check_codebase(working_dir, test_name)
assert response.returncode == 0, response.stdout
+
+
+def test_template_fail() -> None:
+ test_name = "production_beaker_smart_contract_fail"
+
+ response = run_init(
+ root,
+ test_name,
+ answers={
+ "preset_name": "starter",
+ "deployment_language": "python",
+ },
+ )
+ assert response.returncode == 1, response.stdout
diff --git a/tests/test_templates.py b/tests/test_templates.py
index 2dfa162..fcc8da7 100644
--- a/tests/test_templates.py
+++ b/tests/test_templates.py
@@ -186,6 +186,7 @@ def get_questions_from_copier_yaml(
@pytest.mark.parametrize(("question_name", "answer"), get_questions_from_copier_yaml())
+@pytest.mark.skip(reason="This test is deprecated since the template is deprecated")
def test_parameters(working_dir: Path, question_name: str, answer: str | bool) -> None:
response = run_init_kwargs(working_dir, **{question_name: answer})
assert response.returncode == 0, response.stdout
From 8f7cccdb44d56997226db86cd2e1637c6b9912b9 Mon Sep 17 00:00:00 2001
From: Altynbek Orumbayev
Date: Fri, 22 Nov 2024 10:11:55 +0500
Subject: [PATCH 3/5] chore: deprecate beaker template with explicit question +
warning & exit task
---
copier.yaml | 53 ++++++++++++++++++++++++-----------
template_content/post_init.py | 35 +++++++++++++++++++++++
2 files changed, 72 insertions(+), 16 deletions(-)
create mode 100644 template_content/post_init.py
diff --git a/copier.yaml b/copier.yaml
index 0d1d637..8e7c2c0 100644
--- a/copier.yaml
+++ b/copier.yaml
@@ -1,33 +1,50 @@
_subdirectory: template_content
_templates_suffix: ".jinja"
-_tasks:
- - "python -c \"print('WARNING: This template has been deprecated. Beaker for Algorand Smart Contract development is no longer supported.\\nPlease use Algorand Python instead. The Algorand Python template can be found at https://github.com/algorandfoundation/algokit-python-template')\""
- - "python -c \"exit(1)\""
+use_deprecated_template:
+ type: bool
+ help: |
+ WARNING: This template has been deprecated. Beaker for Algorand Smart Contract development is no longer supported.
+ Please use Algorand Python instead. The Algorand Python template can be found at https://github.com/algorandfoundation/algokit-python-template
+ Do you still want to proceed with using the deprecated template?
+ default: no
+_tasks:
+ - '"{{ python_path if python_path else _copier_python }}" post_init.py {{ use_deprecated_template }} {{ use_workspace }}'
+
use_workspace:
type: bool
- when: false # never prompted to user explicitly, instead expect cli to auto fill (supported cli versions > v1.13.x)
+ when: false # never prompted to user explicitly, expect CLI to auto-fill
help: Automatically filled by AlgoKit CLI (>1.13.x) - passes the --workspace/--no-workspace flag's value, can be used to reason whether this template is currently being instantiated as part of a workspace or not.
default: no
+# 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
+
# questions
project_name:
type: str
help: Name for this project.
placeholder: "algorand-app"
+ when: "{{ use_deprecated_template }}"
author_name:
type: str
help: Package author name
placeholder: "Your Name"
default: "Your Name"
+ when: "{{ use_deprecated_template }}"
author_email:
type: str
help: Package author email
placeholder: "your@email.tld"
default: "your@email.tld"
+ when: "{{ use_deprecated_template }}"
contract_name:
type: str
@@ -38,6 +55,7 @@ contract_name:
{% if not (contract_name | regex_search('^[a-z]+(?:_[a-z]+)*$')) %}
contract_name must be formatted in snake case.
{% endif %}
+ when: "{{ use_deprecated_template }}"
preset_name:
type: str
@@ -47,6 +65,7 @@ preset_name:
"Production - for confidently deploying to MainNet and/or more complex projects": "production"
"Custom - for tailoring the template output to your needs": "custom"
default: "starter"
+ when: "{{ use_deprecated_template }}"
deployment_language:
type: str
@@ -55,41 +74,43 @@ deployment_language:
Python: "python"
TypeScript: "typescript"
default: "python"
+ when: "{{ use_deprecated_template }}"
ide_vscode:
type: bool
help: Do you want to add VSCode configuration?
- when: "{{ preset_name == 'custom' }}"
+ when: "{{ preset_name == 'custom' and use_deprecated_template }}"
default: yes
code_tours:
type: bool
help: Do you want to add interactive VSCode CodeTour walkthrough?
- when: "{{ preset_name == 'custom' }}"
+ when: "{{ preset_name == 'custom' and use_deprecated_template }}"
default: yes
ide_jetbrains:
type: bool
help: Do you want to add JetBrains configuration (primarily optimized for PyCharm CE)?
- when: "{{ preset_name == 'custom' }}"
+ when: "{{ preset_name == 'custom' and use_deprecated_template }}"
default: "{{ 'yes' if preset_name == 'production' else 'no' }}"
+ when: "{{ use_deprecated_template }}"
use_python_pytest:
type: bool
- when: "{{ deployment_language == 'python' and preset_name == 'custom' }}"
+ when: "{{ deployment_language == 'python' and preset_name == 'custom' and use_deprecated_template }}"
help: Do you want to include unit tests (via pytest)?
default: "{{ 'yes' if preset_name == 'production' and deployment_language == 'python' else 'no' }}"
use_typescript_jest:
type: bool
- when: "{{ deployment_language == 'typescript' and preset_name == 'custom' }}"
+ when: "{{ deployment_language == 'typescript' and preset_name == 'custom' and use_deprecated_template }}"
help: Do you want to include unit tests (via jest)?
default: "{{ 'yes' if preset_name == 'production' and deployment_language == 'typescript' else 'no' }}"
python_linter:
type: str
help: Do you want to use a Python linter?
- when: "{{ preset_name == 'custom' }}"
+ when: "{{ preset_name == 'custom' and use_deprecated_template }}"
choices:
Ruff: "ruff"
Flake8: "flake8"
@@ -99,35 +120,35 @@ python_linter:
use_python_black:
type: bool
help: Do you want to use a Python formatter (via Black)?
- when: "{{ preset_name == 'custom' }}"
+ when: "{{ preset_name == 'custom' and use_deprecated_template }}"
default: "{{ 'yes' if preset_name == 'production' else 'no' }}"
use_python_mypy:
type: bool
- when: "{{ preset_name == 'custom' }}"
+ when: "{{ preset_name == 'custom' and use_deprecated_template }}"
help: Do you want to use a Python type checker (via mypy)?
default: "{{ 'yes' if preset_name == 'production' else 'no' }}"
use_python_pip_audit:
type: bool
- when: "{{ preset_name == 'custom' }}"
+ when: "{{ preset_name == 'custom' and use_deprecated_template }}"
help: Do you want to include Python dependency vulnerability scanning (via pip-audit)?
default: "{{ 'yes' if preset_name == 'production' else 'no' }}"
use_github_actions:
type: bool
- when: "{{ preset_name == 'custom' }}"
+ when: "{{ preset_name == 'custom' and use_deprecated_template }}"
help: Do you want to include Github Actions workflows for build and testnet deployment?
default: "{{ 'yes' if preset_name == 'production' else 'no' }}"
use_pre_commit:
type: bool
- when: "{{ preset_name == 'custom' }}"
+ when: "{{ preset_name == 'custom' and use_deprecated_template }}"
help: Do you want to include pre-commit for linting, type checking and formatting?
default: "{{ 'yes' if preset_name == 'production' else 'no' }}"
use_dispenser:
type: bool
- when: "{{ preset_name == 'custom' }}"
+ when: "{{ preset_name == 'custom' and use_deprecated_template }}"
help: Do you want to fund your deployment account using an optional dispenser account?
default: "{{ 'yes' if preset_name == 'production' else 'no' }}"
diff --git a/template_content/post_init.py b/template_content/post_init.py
new file mode 100644
index 0000000..56a4400
--- /dev/null
+++ b/template_content/post_init.py
@@ -0,0 +1,35 @@
+import shutil
+import sys
+from pathlib import Path
+
+
+def main():
+ # Get the use_deprecated_template argument
+ use_deprecated_template = sys.argv[1].lower() in ("true", "yes", "1", "t", "y")
+ use_workspace = sys.argv[2].lower() in ("true", "yes", "1", "t", "y")
+
+ if not use_deprecated_template:
+ # Get the parent directory of this script which should be the generated project root
+ project_dir = Path(__file__).parent
+ project_dir = project_dir.parent.parent if use_workspace else project_dir
+
+ # Print warning
+ print("WARNING: Template generation cancelled!\n")
+ print(
+ "This template is deprecated. Use Algorand Python instead: https://github.com/algorandfoundation/algokit-python-template\n"
+ )
+
+ if project_dir.exists():
+ try:
+ shutil.rmtree(project_dir)
+ except:
+ pass
+
+ sys.exit(1)
+
+ # If we get here, template was approved to be used
+ print("Proceeding with deprecated template generation...")
+
+
+if __name__ == "__main__":
+ main()
From e9e7e373e256b4091a09a4093e96c7e201b2a819 Mon Sep 17 00:00:00 2001
From: David Rojas
Date: Fri, 22 Nov 2024 14:21:15 -0500
Subject: [PATCH 4/5] chore: changed working dir before deleting template dir
and added more err handling
---
template_content/post_init.py | 24 ++++++++++++++++++++++--
1 file changed, 22 insertions(+), 2 deletions(-)
diff --git a/template_content/post_init.py b/template_content/post_init.py
index 56a4400..1d21c43 100644
--- a/template_content/post_init.py
+++ b/template_content/post_init.py
@@ -1,6 +1,7 @@
import shutil
import sys
from pathlib import Path
+import os
def main():
@@ -21,9 +22,28 @@ def main():
if project_dir.exists():
try:
+ # Change working directory to parent before deletion
+ os.chdir(project_dir.parent)
shutil.rmtree(project_dir)
- except:
- pass
+ except PermissionError as e:
+ print(
+ f"Failed to clean up {project_dir}: Unable to remove directory due to permissions: {e}",
+ file=sys.stderr,
+ )
+ print(
+ "Please ensure no files are open in the directory and try again.",
+ file=sys.stderr,
+ )
+ sys.exit(1)
+ except OSError as e:
+ print(f"Failed to clean up {project_dir}: {str(e)}", file=sys.stderr)
+ print(
+ "Please ensure no files are open in the directory and try again.",
+ file=sys.stderr,
+ )
+ sys.exit(1)
+ except Exception as e:
+ print(f"Failed to clean up {project_dir}: {str(e)}", file=sys.stderr)
sys.exit(1)
From 159fe6472290f6cdc6c4c1cd55d3dbde250ea7c0 Mon Sep 17 00:00:00 2001
From: David Rojas
Date: Tue, 26 Nov 2024 15:19:27 -0500
Subject: [PATCH 5/5] chore: Removed other exceptions. Kept generic exception
---
template_content/post_init.py | 19 ++-----------------
1 file changed, 2 insertions(+), 17 deletions(-)
diff --git a/template_content/post_init.py b/template_content/post_init.py
index 1d21c43..b312e50 100644
--- a/template_content/post_init.py
+++ b/template_content/post_init.py
@@ -22,28 +22,13 @@ def main():
if project_dir.exists():
try:
- # Change working directory to parent before deletion
os.chdir(project_dir.parent)
shutil.rmtree(project_dir)
- except PermissionError as e:
- print(
- f"Failed to clean up {project_dir}: Unable to remove directory due to permissions: {e}",
- file=sys.stderr,
- )
- print(
- "Please ensure no files are open in the directory and try again.",
- file=sys.stderr,
- )
- sys.exit(1)
- except OSError as e:
- print(f"Failed to clean up {project_dir}: {str(e)}", file=sys.stderr)
+ except Exception as e:
print(
- "Please ensure no files are open in the directory and try again.",
+ f"Failed to clean up {project_dir}. You will have to manually delete the project folder. Error: {str(e)}",
file=sys.stderr,
)
- sys.exit(1)
- except Exception as e:
- print(f"Failed to clean up {project_dir}: {str(e)}", file=sys.stderr)
sys.exit(1)