Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions .github/workflows/release.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
name: "publish"

on:
push:
tags:
# Publish on any tag starting with a `v`, e.g., v0.1.0
- v*

jobs:
run:
runs-on: ubuntu-latest
environment:
name: pypi
permissions:
id-token: write
contents: read
steps:
- name: Checkout
uses: actions/checkout@v5
- name: Install uv
uses: astral-sh/setup-uv@v7
- name: Install Python 3.13
run: uv python install 3.13
- name: Build
run: uv build
# Check that basic features work and we didn't miss to include crucial files
- name: Smoke test (wheel)
run: uv run --isolated --no-project --with dist/*.whl tests/smoke_test.py
- name: Smoke test (source distribution)
run: uv run --isolated --no-project --with dist/*.tar.gz tests/smoke_test.py
- name: Publish
run: uv publish
14 changes: 3 additions & 11 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,7 @@
Changelog: dsd-<platformname>
===
# Changelog: dsd-pythonanywhere

0.1 - Provisional support for deployments
---
## 0.1 - Provisional support for deployments

### 0.1.0

#### External changes

-

#### Internal changes

-
- Initial testing release
2 changes: 0 additions & 2 deletions MANIFEST.in

This file was deleted.

28 changes: 27 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ deployments yet.
- [Approach](#approach)
- [Plugin Development](#plugin-development)
- [Automated Tests](#automated-tests)
- [Releasing](#releasing)

## Motivation

Expand Down Expand Up @@ -53,7 +54,7 @@ you can deploy your project with the following steps:
export API_USER=[your_pythonanywhere_username]
export API_TOKEN=[your_pythonanywhere_api_token]
# Install dsd-pythonanywhere (which also installs django-simple-deploy)
pip install git+https://github.com/caktus/dsd-pythonanywhere.git@main
pip install dsd-pythonanywhere
```

2. Add `django-simple-deploy` to your `INSTALLED_APPS` in `settings.py`:
Expand Down Expand Up @@ -273,3 +274,28 @@ uv run pytest
# To skip platform_agnostic_tests for faster feedback during plugin development:
uv run pytest --ignore=tests/integration_tests/platform_agnostic_tests
```

### Releasing

1. Bump the version in `pyproject.toml`:
```sh
uv version --bump patch # or --bump minor/major
```

2. Add release notes to `CHANGELOG.md`

3. Create a new release on GitHub:
- Tag the version (e.g., `v0.2.1`)
- Add the same release notes
- Publish the release

When the release is published, CI automatically builds and publishes the package to PyPI.

<!-- omit in toc -->
#### Test Release

If you're testing a release, you can use `test.pypi.org` with a command like:

```sh
op run --env-file ../.testpypi -- uv publish --publish-url https://test.pypi.org/legacy/
```
7 changes: 7 additions & 0 deletions dsd_pythonanywhere/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1,8 @@
try:
from importlib.metadata import version

__version__ = version("dsd-pythonanywhere")
except Exception:
__version__ = "unknown"

from .deploy import dsd_deploy, dsd_get_plugin_config # noqa: F401
1 change: 1 addition & 0 deletions dsd_pythonanywhere/deploy.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import django_simple_deploy

from dsd_pythonanywhere.platform_deployer import PlatformDeployer

from .plugin_config import PluginConfig


Expand Down
25 changes: 0 additions & 25 deletions dsd_pythonanywhere/templates/dockerfile_example

This file was deleted.

68 changes: 41 additions & 27 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,70 +1,83 @@
[build-system]
requires = ["setuptools"]
build-backend = "setuptools.build_meta"
requires = ["hatchling"]
build-backend = "hatchling.build"

[project]
name = "dsd-pythonanywhere"
version = "0.1.0"
description = "A plugin for django-simple-deploy, supporting deployments to PythonAnywhere."
readme = "README.md"
requires-python = ">=3.10"
license = "BSD-3-Clause"
license-files = ["LICEN[CS]E.*"]

authors = [
{name = "Caktus Consulting Group", email = "[email protected]" },
]

classifiers = [
"Development Status :: 4 - Beta",
"Framework :: Django",
"Framework :: Django :: 4.2",
"Framework :: Django :: 5.0",
"Framework :: Django :: 5.1",
"Framework :: Django :: 5.2",
"Framework :: Django :: 6.0",
"Intended Audience :: Developers",
"License :: OSI Approved :: BSD License",
"Operating System :: OS Independent",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3 :: Only",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
"Programming Language :: Python :: 3.13",
"Programming Language :: Python :: 3.14",
"Topic :: Software Development :: Build Tools",
"Topic :: System :: Software Distribution",
]

keywords = ["django", "deployment"]

requires-python = ">=3.9"
keywords = ["django", "deployment", "pythonanywhere", "simple-deploy"]

dependencies = [
"django>=4.2",
"pluggy>=1.5.0",
"toml>=0.10.2",
"requests>=2.32.2",
"django-simple-deploy>=0.9.0",
"pythonanywhere>=0.15.5",
"pythonanywhere-core>=0.2.4",
"requests>=2.32.2",
"pluggy>=1.5.0",
"tomli>=2.0.1; python_version < '3.11'",
]

[project.optional-dependencies]
dev = [
"build>=1.2.1",
"pytest>=8.3.0",
"pytest-mock>=3.15.1",
"twine>=5.1.1",
]
[project.urls]
Homepage = "https://github.com/caktus/dsd-pythonanywhere"
Source = "https://github.com/caktus/dsd-pythonanywhere"
Tracker = "https://github.com/caktus/dsd-pythonanywhere/issues"

# [project.urls]
# "Documentation" = "<documentation URL>"
# "GitHub" = "<GH repo URL>"
# "Changelog" = "<changelog URL"
# --- HATCHLING SPECIFIC CONFIGURATION ---

[tool.setuptools]
packages = [
# BUILD TARGETS
# This replaces MANIFEST.in.
# Hatchling includes everything in git by default, but we can be explicit.
[tool.hatch.build.targets.sdist]
include = [
"dsd_pythonanywhere",
"dsd_pythonanywhere.templates",
"LICENSE",
"README.md",
]
include-package-data = true

[tool.hatch.build.targets.wheel]
packages = ["dsd_pythonanywhere"]

# --- TOOL CONFIGURATION ---

[tool.ruff]
line-length = 100
exclude = ["dsd_pythonanywhere/templates/settings.py"]
exclude = [
"dsd_pythonanywhere/templates/settings.py",
"build",
"dist",
]

[dependency-groups]
dev = [
Expand All @@ -76,4 +89,5 @@ dev = [
]

[tool.pytest.ini_options]
testpaths = [ "tests/unit_tests" ]
testpaths = ["tests/unit_tests"]
addopts = "--verbose"
2 changes: 1 addition & 1 deletion tests/e2e_tests/test_deployment.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
import pytest

from tests.e2e_tests.utils import it_helper_functions as it_utils
from . import utils as platform_utils

from . import utils as platform_utils

# --- Test functions ---

Expand Down
33 changes: 33 additions & 0 deletions tests/smoke_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
"""Basic smoke test to verify package installation."""

import sys
from pathlib import Path

# Verify package can be imported
import dsd_pythonanywhere

# Verify version is set
assert hasattr(dsd_pythonanywhere, "__version__"), "Missing __version__ attribute"
print(f"✓ Package version: {dsd_pythonanywhere.__version__}")

# Verify main exports exist
assert hasattr(dsd_pythonanywhere, "dsd_deploy"), "Missing dsd_deploy export"
assert hasattr(dsd_pythonanywhere, "dsd_get_plugin_config"), "Missing dsd_get_plugin_config export"
print("✓ Main exports found")

# Verify templates directory is included
package_path = Path(dsd_pythonanywhere.__file__).parent
templates_dir = package_path / "templates"
assert templates_dir.exists(), f"Templates directory not found at {templates_dir}"
assert templates_dir.is_dir(), f"Templates path exists but is not a directory: {templates_dir}"
print(f"✓ Templates directory found: {templates_dir}")

# Verify template files exist
expected_templates = ["settings.py", "wsgi.py"]
for template in expected_templates:
template_path = templates_dir / template
assert template_path.exists(), f"Missing template file: {template}"
print(f" ✓ Found: {template}")

print("\n✅ All smoke tests passed!")
sys.exit(0)
Loading