Skip to content

Commit b1bc531

Browse files
authored
🐳 [GH-67] Add DigitalOcean app-platform deploy support (#73)
* feat: add digitalocean app-platform deploy option [#67] * fix: yaml updates after testing [#67] * chore: clean up yaml [#67] * chore: fix do deploy and update documentation [#67] * docs: update README [#67] * docs: clean up [#67] * fix: add missing env vars from deploy step [#67]
1 parent 5a706bd commit b1bc531

13 files changed

Lines changed: 217 additions & 8 deletions

File tree

.github/workflows/main.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ jobs:
1919
uses: ./.github/workflows/test.yml
2020

2121
create-release:
22+
if: startsWith(github.ref, 'refs/tags/')
2223
permissions:
2324
contents: write
2425
needs: [lint, tests]

README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,12 @@
1919

2020
Supported PaaS's:
2121
- Render
22+
- DigitalOcean
2223
- Platform.sh (Coming soon)
2324
- Fly.io (Coming soon)
24-
- DigitalOcean (Coming soon)
2525

2626
## Quickstart
27-
Install the latest Cookiecutter if you haven't installed it yet (this requires Cookiecutter 1.4.0 or higher):
27+
Install the latest Cookiecutter if you haven't installed it yet:
2828
```sh
2929
# pipx is strongly recommended.
3030
$ pipx install cookiecutter
@@ -57,7 +57,7 @@ cookiecutter("gh:nickatnight/cookiecutter-fastapi-backend")
5757
* :convenience_store: **Redis** In-memory data structure [store](https://redis.io/), used as a distributed, in-memory key–value database, cache and message broker
5858
* :gear: **Common** Base models and repository classes for common CRUD operations and database schemas.
5959
* :seedling: **Celery** [Asynchronous](https://docs.celeryq.dev/en/stable/getting-started/introduction.html) task or job queue
60-
* :inbox_tray: **Continuous Integration/Deployment** Modular [GitHub Actions](https://github.com/features/actions) to lint, test, and deploy to your favorite platform. Automatically includes [Codecov](https://about.codecov.io/) reporting.
60+
* :inbox_tray: **Continuous Integration/Deployment** Modular [GitHub Actions](https://github.com/features/actions) to lint, test, and deploy to your favorite platform-as-a-service. Automatically includes [Codecov](https://about.codecov.io/) reporting.
6161
* :leftwards_arrow_with_hook: **pre-commit** [Git hooks](https://pre-commit.com/) to maintain code quality using modern tooling (ruff, black, isort)
6262
* :rocket: **Sentry** Application monitoring and error tracking. You can sign up for free at [sentry.io](https://sentry.io/)
6363

@@ -76,7 +76,7 @@ The input variables, with their default values (some auto generated) are:
7676
* `use_celery`: Whether to use Celery/Beat and Redis for asynchronous/scheduled tasks. Default `no`
7777
* `use_sentry`: Whether to use Sentry for application monitoring and error tracking. Default `no`
7878
* `github_username`: The username of the GitHub user. Used for badge display in generated project `README.md`
79-
* `deployments`: Deploy to your favorite platform, Render.com (and more to come). Default `none`
79+
* `deployments`: Deploy to your favorite platform, Render.com, DigitalOcean, (and more to come). Default `none`
8080

8181
## Documentation
8282
See full documentation [here](https://cookiecutter-fastapi-backend.readthedocs.io/en/latest/).

cookiecutter.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,5 @@
1313
"use_sentry": ["no", "yes"],
1414
"github_username": "change.me",
1515

16-
"deployments": ["none", "render"]
16+
"deployments": ["none", "render", "digitalocean"]
1717
}

docs/source/project_features/deploy.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,6 @@ Deployments for this project are meant to be painless, and to be achieved in a f
77
:maxdepth: 1
88
:caption: Deployments
99

10+
deployments/digitalocean
1011
deployments/render
1112
deployments/platformsh
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
DigitalOcean
2+
============
3+
4+
There a couple of house keeping steps to take before deploying to DigitalOcean. You can
5+
read more about the steps `here <https://docs.digitalocean.com/products/app-platform/how-to/deploy-from-github-actions/#prerequisites>`_.
6+
7+
.. note::
8+
9+
Be sure you have the official `DigitalOcean GitHub App <https://cloud.digitalocean.com/apps/github/install>`_ installed in your GitHub account.
10+
It is recommended to only allow the app to access the repositories you want to deploy.
11+
12+
Meaning, once your project has been scaffolded with this cookiecutter, you'll have to push
13+
it to GitHub for it to be available to DigitalOcean.
14+
15+
Once the prerequisites are met:
16+
--------------------------------
17+
18+
Provision the app using the provided script ``bin/provision-app.sh``.
19+
20+
.. code-block:: bash
21+
22+
$ ./bin/provision-app.sh
23+
24+
This creates app based on the spec file ``digitalocean.yaml`` at the root of the project. The services will get created, but
25+
will fail deployment, which is expected. They fail because we've deployed the app from the CLI without any of the environment variables.
26+
27+
Ensure the following variables are in the Apps Environment Variables, and in your GitHub repository secrets:
28+
29+
- ``POSTGRES_USER``
30+
- ``POSTGRES_PASSWORD``
31+
- ``POSTGRES_DB``
32+
- ``POSTGRES_HOST``
33+
- ``POSTGRES_PORT``
34+
35+
.. note::
36+
37+
The environment variables are injected into the ``deploy-app`` step in the GitHub Actions workflow.
38+
39+
Once saved, the deployment for the app will get re-triggered, and the services will be deployed successfully. Now, any merges into your main branch will trigger a deployment.

hooks/post_gen_project.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
]
1111
DEPLOYMENT_FILES = [
1212
"render.yaml",
13+
"digitalocean.yaml",
1314
]
1415

1516

@@ -32,6 +33,17 @@ def rename_file(old: str, new: str):
3233
for p in DEPLOYMENT_FILES:
3334
remove_file(p)
3435

36+
37+
if "{{ cookiecutter.deployments }}" == "render":
38+
print("Removing digitalocean deployment file(s)...")
39+
remove_file("digitalocean.yaml")
40+
41+
42+
if "{{ cookiecutter.deployments }}" == "digitalocean":
43+
print("Removing render deployment file(s)...")
44+
remove_file("render.yaml")
45+
46+
3547
if "{{ cookiecutter.use_celery }}" == "no":
3648
print("Removing celery files...")
3749
for p in CELERY_FILE_PATHS:

pyproject.toml

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "cookiecutter-fastapi-backend"
3-
version = "2.3.0"
3+
version = "2.4.0"
44
description = "Cookiecutter template to build and deploy fastapi backends..batteries included"
55
authors = [{ name = "nickatnight", email = "nialexanderke@proton.me" }]
66
requires-python = ">=3.9"
@@ -9,15 +9,31 @@ dependencies = [
99
"cookiecutter==2.6.0",
1010
]
1111
classifiers = [
12+
"Development Status :: 4 - Beta",
13+
"Environment :: Console",
1214
"Framework :: FastAPI",
1315
"Intended Audience :: Developers",
16+
"Natural Language :: English",
1417
"Programming Language :: Python :: 3",
1518
"Programming Language :: Python :: 3.10",
1619
"Programming Language :: Python :: 3.11",
1720
"Programming Language :: Python :: 3.12",
1821
"Programming Language :: Python :: 3.13",
1922
"Topic :: Software Development :: Code Generators"
2023
]
24+
keywords=[
25+
"cookiecutter",
26+
"Python",
27+
"projects",
28+
"project templates",
29+
"Jinja2",
30+
"skeleton",
31+
"scaffolding",
32+
"project directory",
33+
"package",
34+
"packaging",
35+
"FastAPI"
36+
]
2137

2238
[project.urls]
2339
Homepage = "https://github.com/nickatnight/cookiecutter-fastapi-backend"

tests/test_bake_project.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
SUPPORTED_COMBINATIONS = [
2121
{"deployments": "none"},
2222
{"deployments": "render"},
23+
{"deployments": "digitalocean"},
2324
{"use_celery": "no"},
2425
{"use_celery": "yes"},
2526
{"py_version": "3.9"},

uv.lock

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

{{ cookiecutter.project_slug }}/.github/workflows/main.yml

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ jobs:
1616
uses: ./.github/workflows/unit-tests.yml
1717

1818
create-release:
19+
if: startsWith(github.ref, 'refs/tags/')
1920
permissions:
2021
contents: write
2122
runs-on: ubuntu-latest
@@ -27,8 +28,26 @@ jobs:
2728
- name: Create Release
2829
id: create_release
2930
uses: nickatnight/releases-action@v5
30-
if: startsWith(github.ref, 'refs/tags/')
3131
{% raw %}env:
3232
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}{% endraw %}
3333
{% raw %}outputs:
3434
ReleaseTag: ${{ steps.create_release.outputs.release_tag }}{% endraw %}
35+
{%- if cookiecutter.deployments == "digitalocean" %}
36+
deploy-app:
37+
runs-on: ubuntu-latest
38+
steps:
39+
- name: Checkout repository
40+
uses: actions/checkout@v4
41+
- name: Deploy the app
42+
uses: digitalocean/app_action/deploy@v2
43+
{% raw %}env:
44+
DIGITALOCEAN_ACCESS_TOKEN: ${{ secrets.DIGITALOCEAN_ACCESS_TOKEN }}
45+
POSTGRES_USER: ${{ secrets.POSTGRES_USER }}
46+
POSTGRES_PASSWORD: ${{ secrets.POSTGRES_PASSWORD }}
47+
POSTGRES_DB: ${{ secrets.POSTGRES_DB }}
48+
POSTGRES_HOST: ${{ secrets.POSTGRES_HOST }}
49+
POSTGRES_PORT: ${{ secrets.POSTGRES_PORT }}
50+
with:
51+
app_spec_location: digitalocean.yaml
52+
token: ${{ secrets.DIGITALOCEAN_ACCESS_TOKEN }}{% endraw %}
53+
{%- endif %}

0 commit comments

Comments
 (0)