Skip to content

Commit 37bb290

Browse files
committed
copy wsgi file after creating web app
1 parent bc19fad commit 37bb290

File tree

5 files changed

+33
-58
lines changed

5 files changed

+33
-58
lines changed

README.md

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,10 @@ yet recommended for actual deployments yet.
1010

1111
## Motivation
1212

13-
This plugin is motivated by the desire to provide a deployment option for
14-
`django-simple-deploy` that doesn't require a credit card to get started.
15-
PythonAnywhere offers a free tier that allows users to deploy small Django apps
16-
and may be a helpful way to get small Django apps online without financial
17-
commitment.
13+
This plugin hopes to provide a deployment option for `django-simple-deploy` that
14+
doesn't require a credit card to get started. PythonAnywhere offers a free tier
15+
that allows users to deploy small Django apps and may be a helpful way to get
16+
small Django apps online without financial commitment.
1817

1918
## Quickstart
2019

@@ -28,7 +27,7 @@ requires a few prerequisites:
2827
which is a limited account with one web app, but requires no credit card.
2928
- Generate an [API token](https://help.pythonanywhere.com/pages/GettingYourAPIToken)
3029
- Ideally, stay logged in to PythonAnywhere in your default browser to make the
31-
first deployment smoother.
30+
deployment smoother.
3231

3332
## Plugin Development
3433

dsd_pythonanywhere/platform_deployer.py

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -143,30 +143,42 @@ def _prep_automate_all(self):
143143
"""Take any further actions needed if using automate_all."""
144144
pass
145145

146-
def _clone_and_run_setup_script(self):
146+
def _clone_and_run_setup_script(self, repo_name: str):
147147
# Run the setup script to clone repo and install dependencies
148148
cmd = [f"curl -fsSL {REMOTE_SETUP_SCRIPT_URL} | bash -s --"]
149149
origin_url = self._get_origin_url()
150-
repo_name = self._get_repo_name()
151150
django_project_name = dsd_config.local_project_name
152151
cmd.append(f"{origin_url} {repo_name} {django_project_name}")
153152
cmd = " ".join(cmd)
154153
plugin_utils.write_output(f" Cloning and running setup script: {cmd}")
155154
self.client.run_command(cmd)
156155
plugin_utils.write_output("Done cloning and running setup script.")
157-
# Finally, create the webapp
158-
self._create_webapp(client=self.client, repo_name=repo_name)
159156

160-
def _create_webapp(self, client: PythonAnywhereClient, repo_name: str):
157+
def _copy_wsgi_file(self, repo_name: str):
158+
"""Copy wsgi.py to PythonAnywhere's wsgi location.
159+
160+
This must be done after webapp creation, as creating a webapp
161+
overwrites the wsgi file.
162+
"""
163+
plugin_utils.write_output(" Copying wsgi.py to PythonAnywhere...")
164+
165+
django_project_name = dsd_config.local_project_name
166+
domain = f"{self.client.username}.pythonanywhere.com"
167+
wsgi_dest = f"/var/www/{domain.replace('.', '_')}_wsgi.py"
168+
wsgi_src = f"{repo_name}/{django_project_name}/wsgi.py"
169+
170+
cmd = f"cp {wsgi_src} {wsgi_dest}"
171+
self.client.run_command(cmd)
172+
plugin_utils.write_output(f" Copied {wsgi_src} to {wsgi_dest}")
173+
174+
def _create_webapp(self, repo_name: str):
161175
"""Create the webapp on PythonAnywhere."""
162176
plugin_utils.write_output(" Creating webapp on PythonAnywhere...")
163-
164177
# Paths on PythonAnywhere (remote home directory)
165-
remote_home = Path(f"/home/{client.username}")
178+
remote_home = Path(f"/home/{self.client.username}")
166179
project_path = remote_home / repo_name
167180
virtualenv_path = remote_home / "venv"
168-
169-
client.create_or_update_webapp(
181+
self.client.create_or_update_webapp(
170182
python_version="3.13",
171183
virtualenv_path=virtualenv_path,
172184
project_path=project_path,
@@ -232,10 +244,10 @@ def _conclude_automate_all(self):
232244

233245
# Push project.
234246
plugin_utils.write_output(" Deploying to PythonAnywhere...")
235-
236-
# Should set self.deployed_url, which will be reported in the success message.
237-
self._clone_and_run_setup_script()
238-
247+
repo_name = self._get_repo_name()
248+
self._clone_and_run_setup_script(repo_name=repo_name)
249+
self._create_webapp(repo_name=repo_name)
250+
self._copy_wsgi_file(repo_name=repo_name)
239251
self.deployed_url = f"https://{self._get_deployed_project_name()}.pythonanywhere.com"
240252

241253
def _show_success_message(self):

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ description = "A plugin for django-simple-deploy, supporting deployments to Pyth
99
readme = "README.md"
1010

1111
authors = [
12-
{name = "Eric Matthes", email = "ehmatthes@gmail.com" },
12+
{name = "Caktus Consulting Group", email = "solutions@caktusgroup.com" },
1313
]
1414

1515
classifiers = [

scripts/setup.sh

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,14 @@
22
set -e
33

44
if [ -z "$1" ] || [ -z "$2" ] || [ -z "$3" ]; then
5-
echo "Usage: $0 <git-repo-url> <directory-name> <django-project-name> [python-version] [wsgi-dest-prefix]"
5+
echo "Usage: $0 <git-repo-url> <directory-name> <django-project-name> [python-version]"
66
exit 1
77
fi
88

99
GIT_REPO_URL=$1
1010
REPO_NAME=$2
1111
DJANGO_PROJECT_NAME=$3
1212
PYTHON_VERSION=${4:-python3.13}
13-
WSGI_DEST_PREFIX=${5:-/var/www}
1413

1514
# Clone the repository from the provided Git URL
1615

@@ -56,15 +55,4 @@ else
5655
echo ".env file already exists. Skipping creation."
5756
fi
5857

59-
# Copy wsgi.py to PythonAnywhere's wsgi location
60-
USERNAME=$(whoami)
61-
DOMAIN="${USERNAME}.pythonanywhere.com"
62-
WSGI_DEST="${WSGI_DEST_PREFIX}/${DOMAIN//./_}_wsgi.py"
63-
WSGI_SRC="$REPO_NAME/$DJANGO_PROJECT_NAME/wsgi.py"
64-
65-
echo "Copying WSGI file from $WSGI_SRC to $WSGI_DEST..."
66-
mkdir -p "$WSGI_DEST_PREFIX"
67-
cp "$WSGI_SRC" "$WSGI_DEST"
68-
echo "WSGI file copied."
69-
7058
echo "Setup complete!!!"

tests/integration_tests/test_setup_script.py

Lines changed: 1 addition & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,11 @@
1-
"""Integration tests for the PythonAnywhere setup.sh script."""
1+
"""Basic happy path tests for the PythonAnywhere setup.sh script."""
22

3-
import getpass
43
import subprocess
54
import sys
65
from pathlib import Path
76

87
import pytest
98

10-
# --- Fixtures ---
11-
129

1310
@pytest.fixture(scope="module")
1411
def setup_script_result(tmp_path_factory) -> dict:
@@ -19,8 +16,6 @@ def setup_script_result(tmp_path_factory) -> dict:
1916
django_project_name = "mysite"
2017
# Use the current Python version available on CI for testing
2118
python_version = f"python{sys.version_info.major}.{sys.version_info.minor}"
22-
# Use a temp directory for WSGI destination prefix
23-
wsgi_dest_prefix = tmp_path / "var_www"
2419

2520
# Create a minimal git repository with a requirements.txt file and Django project
2621
source_repo = tmp_path / "source_repo"
@@ -42,9 +37,7 @@ def setup_script_result(tmp_path_factory) -> dict:
4237
check=True,
4338
capture_output=True,
4439
)
45-
4640
repo_url = source_repo.as_uri()
47-
4841
result = subprocess.run(
4942
[
5043
"bash",
@@ -53,7 +46,6 @@ def setup_script_result(tmp_path_factory) -> dict:
5346
dir_name,
5447
django_project_name,
5548
python_version,
56-
str(wsgi_dest_prefix),
5749
],
5850
cwd=tmp_path,
5951
check=True,
@@ -67,13 +59,9 @@ def setup_script_result(tmp_path_factory) -> dict:
6759
"venv_path": tmp_path / "venv",
6860
"project_path": tmp_path / dir_name,
6961
"django_project_name": django_project_name,
70-
"wsgi_dest_prefix": wsgi_dest_prefix,
7162
}
7263

7364

74-
# --- Test setup.sh script ---
75-
76-
7765
def test_setup_script_creates_venv(setup_script_result):
7866
"""setup.sh creates a virtual environment."""
7967
assert setup_script_result["result"].returncode == 0
@@ -104,15 +92,3 @@ def test_setup_script_creates_env_file(setup_script_result):
10492
if line.startswith("SECRET_KEY="):
10593
secret_key = line.split("=", 1)[1]
10694
assert len(secret_key) == 50
107-
108-
109-
def test_setup_script_copies_wsgi_file(setup_script_result):
110-
"""setup.sh copies WSGI file to the destination prefix."""
111-
username = getpass.getuser()
112-
domain = f"{username}.pythonanywhere.com"
113-
wsgi_filename = f"{domain.replace('.', '_')}_wsgi.py"
114-
wsgi_dest = setup_script_result["wsgi_dest_prefix"] / wsgi_filename
115-
116-
assert "WSGI file copied." in setup_script_result["result"].stdout
117-
assert wsgi_dest.exists()
118-
assert "DJANGO_SETTINGS_MODULE" in wsgi_dest.read_text()

0 commit comments

Comments
 (0)