Skip to content

Commit 0dcfe8a

Browse files
committed
build: add CI/CD and a basic test
1 parent d6d2cf4 commit 0dcfe8a

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+1551
-1
lines changed

.github/workflows/cd.yaml

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
name: Continuous Delivery of Template
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
8+
concurrency: release
9+
10+
jobs:
11+
ci-check-python:
12+
name: Check Python
13+
uses: ./.github/workflows/check-python.yaml
14+
15+
tag-release:
16+
runs-on: "ubuntu-latest"
17+
steps:
18+
- name: Checkout source code
19+
uses: actions/checkout@v3
20+
21+
- name: Tag release
22+
id: tag
23+
uses: TriPSs/conventional-changelog-action@v3.18.0
24+
with:
25+
skip-commit: "true"
26+
tag-prefix: ""
27+
skip-on-empty: "false"
28+
29+
- name: Create Release
30+
uses: softprops/action-gh-release@v1
31+
if: ${{ steps.tag.outputs.skipped == 'false' }}
32+
env:
33+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
34+
with:
35+
tag_name: ${{ steps.tag.outputs.tag }}
36+
body: ${{ steps.tag.outputs.clean_changelog }}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
name: Check Template
2+
3+
on:
4+
workflow_call:
5+
6+
jobs:
7+
check-python:
8+
runs-on: "ubuntu-latest"
9+
steps:
10+
- name: Checkout source code
11+
uses: actions/checkout@v3
12+
13+
- name: Install poetry
14+
run: pipx install poetry
15+
16+
- name: Install algokit
17+
run: pipx install algokit
18+
19+
- name: Set up Python 3.10
20+
uses: actions/setup-python@v4
21+
with:
22+
python-version: "3.10"
23+
cache: "poetry"
24+
25+
- name: Install dependencies
26+
run: poetry install --no-interaction --no-root
27+
28+
- name: Configure git
29+
shell: bash
30+
run: |
31+
# set git user and email as test invoke git
32+
git config --global user.email "actions@github.com" && git config --global user.name "github-actions"
33+
34+
- name: Run tests
35+
shell: bash
36+
run: |
37+
set -o pipefail
38+
poetry run pytest --junitxml=pytest-junit.xml
39+
40+
- name: Check generated templates have been reviewed
41+
shell: bash
42+
run: |
43+
# Add untracked files as empty so they come up in diff
44+
git add -N ./tests_generated
45+
# Look for changes in generated templates and error if there are any
46+
git diff --exit-code --minimal ./tests_generated
47+
working-directory: ${{ inputs.working-directory }}

.github/workflows/pr.yaml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
name: Pull Request validation
2+
3+
on: [pull_request]
4+
5+
jobs:
6+
pr-check:
7+
name: Check Python
8+
uses: ./.github/workflows/check-python.yaml

poetry.lock

Lines changed: 67 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ python-dotenv = "^1.0.0"
1515
ruff = "*"
1616
black = {extras = ["d"], version = "*"}
1717
mypy = "*"
18+
pytest = "^7.3.1"
1819

1920
[build-system]
2021
requires = ["poetry-core"]

tests/test_templates.py

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
import re
2+
import shutil
3+
import subprocess
4+
import tempfile
5+
from collections.abc import Iterator
6+
from pathlib import Path
7+
8+
import pytest
9+
10+
11+
commit_pattern = re.compile(r"_commit: .*")
12+
src_path_pattern = re.compile(r"_src_path: .*")
13+
tests_path = Path(__file__).parent
14+
root = tests_path.parent
15+
generated_folder = "tests_generated"
16+
generated_root = root / generated_folder
17+
DEFAULT_PARAMETERS = {
18+
"author_name": "None",
19+
"author_email": "None",
20+
}
21+
22+
23+
@pytest.fixture(autouse=True, scope="module")
24+
def working_dir() -> Iterator[Path]:
25+
with tempfile.TemporaryDirectory(ignore_cleanup_errors=True) as temp:
26+
working_dir = Path(temp) / "template"
27+
working_generated_root = working_dir / generated_folder
28+
shutil.copytree(root, working_dir)
29+
subprocess.run(["git", "add", "-A"], cwd=working_dir)
30+
subprocess.run(["git", "commit", "-m", "draft changes", "--no-verify"], cwd=working_dir)
31+
32+
yield working_dir
33+
34+
for src_dir in working_generated_root.iterdir():
35+
dest_dir = generated_root / src_dir.stem
36+
shutil.rmtree(dest_dir, ignore_errors=True)
37+
shutil.copytree(src_dir, dest_dir, dirs_exist_ok=True)
38+
39+
40+
def run_init(
41+
working_dir: Path,
42+
test_name: str,
43+
*args: str,
44+
template_url: str | None = None,
45+
template_branch: str | None = None,
46+
answers: dict[str, str] | None = None,
47+
) -> subprocess.CompletedProcess:
48+
copy_to = working_dir / generated_folder / test_name
49+
shutil.rmtree(copy_to, ignore_errors=True)
50+
if template_url is None:
51+
template_url = str(working_dir)
52+
53+
if template_branch is None:
54+
git_output = subprocess.run(
55+
["git", "rev-parse", "--abbrev-ref", "HEAD"],
56+
cwd=working_dir,
57+
stdout=subprocess.PIPE,
58+
)
59+
template_branch = git_output.stdout.decode("utf-8").strip()
60+
61+
init_args = [
62+
"algokit",
63+
"init",
64+
"--name",
65+
str(copy_to.stem),
66+
"--template-url",
67+
template_url,
68+
"--UNSAFE-SECURITY-accept-template-url",
69+
"--defaults",
70+
"--no-ide",
71+
"--no-git",
72+
"--no-bootstrap",
73+
]
74+
answers = {**DEFAULT_PARAMETERS, **(answers or {})}
75+
76+
for question, answer in answers.items():
77+
init_args.extend(["-a", question, answer])
78+
if template_branch:
79+
init_args.extend(["--template-url-ref", template_branch])
80+
init_args.extend(args)
81+
82+
result = subprocess.run(
83+
init_args,
84+
input="y", # acknowledge that input is not a tty
85+
stdout=subprocess.PIPE,
86+
stderr=subprocess.STDOUT,
87+
text=True,
88+
cwd=copy_to.parent,
89+
)
90+
91+
if result.returncode == 0: # if successful, normalize .copier-answers.yml to make observing diffs easier
92+
copier_answers = Path(copy_to / ".copier-answers.yml")
93+
content = copier_answers.read_text("utf-8")
94+
content = commit_pattern.sub("_commit: <commit>", content)
95+
content = src_path_pattern.sub("_src_path: <src>", content)
96+
copier_answers.write_text(content, "utf-8")
97+
98+
return result
99+
100+
101+
def test_default_parameters(working_dir: Path) -> None:
102+
response = run_init(working_dir, "test_default_parameters")
103+
104+
assert response.returncode == 0
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# AlgoKit template generation answers
2+
# Changes here will be overwritten by Copier; NEVER EDIT MANUALLY
3+
_commit: <commit>
4+
_src_path: <src>
5+
algod_port: 4001
6+
algod_server: http://localhost
7+
algod_token: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
8+
indexer_port: 8980
9+
indexer_server: http://localhost
10+
indexer_token: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
11+
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# Consistent IDE settings: https://editorconfig.org/
2+
root=true
3+
4+
[*]
5+
indent_style = space
6+
indent_size = 2
7+
end_of_line = lf
8+
insert_final_newline = true
9+
10+
[*.py]
11+
indent_size = 4
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# Git configuration: https://git-scm.com/docs/gitattributes
2+
* text=auto eol=lf

0 commit comments

Comments
 (0)