Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Version 0.8 - API integration #25

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
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
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -99,3 +99,5 @@ ENV/

# mypy
.mypy_cache/

.vscode/
16 changes: 16 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,22 @@ All notable changes to this project will be documented in this file.

...

## v0.8

Significant update, with backwards-incompatible changes.
The `Deployment` model has been removed, in favour of direct
integration with the Netlify API. A new view for Wagtail
administrators lists the last ten builds, with the option of
triggering new builds.

### Added

- Admin UI integration with the Netlify build API

### Removed

- Support for Wagtail < 2

## v0.7

### Added
Expand Down
29 changes: 18 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@

Deploy your Wagtail site on Netlify. Features include:

- automatic deployment when pages are published
- the ability to build locally and push them to Netlify, or trigger builds on Netlify's servers
- (optional) automatic deployment when pages are published
- an admin UI for viewing and creating Netlify builds
- a new `netlify` management command
- conversion of Wagtail redirects to Netlify's format

Expand Down Expand Up @@ -48,13 +50,13 @@ The path to the Netlify CLI. *Hint: type `which netlify` to check the location.*

If set, deploy to that specific Netlify site.

If not set, the Netlify CLI might prompt you to select one.
If not set, the Netlify CLI might prompt you to select one. This setting is required for the admin view.

### `NETLIFY_API_TOKEN`

**Default: `None`**

If set, the Netlify CLI will not prompt you to click the authentication link in the console. It can be useful when deployed to a remote server where you don't see the console output.
If set, the Netlify CLI will not prompt you to click the authentication link in the console. It can be useful when deployed to a remote server where you don't see the console output. This setting is required for the admin view.

Connect to your Netlify account to [generate a token](https://app.netlify.com/account/applications) and then set the settings. *Warning: You should never check credentials in your version control system. Use [environment variables](https://django-environ.readthedocs.io/en/latest/) or [local settings file](http://techstream.org/Bits/Local-Settings-in-django) instead.*

Expand All @@ -80,12 +82,17 @@ The URL of a Netlify build hook. If provided, `./manage.py netlify --trigger-bui
on Netlify's servers. This may be useful if you have a headless front-end on Netlify which handles its own static site generation,
e.g. Nuxt, Next or Gatsby. See https://docs.netlify.com/configure-builds/build-hooks/ for more details.

### Optional admin view and endpoints
### Admin view

Netlify can send a webhook after a successful deployment. This app provides an endpoint for that webhook and an admin view of completed deployments. To enable this view:
This view allows Wagtail administrators to see a list of recent Netlify builds, and trigger a new one. Both `NETLIFY_API_TOKEN` and `NETLIFY_SITE_ID` should be available in settings. If `NETLIFY_BUILD_HOOK` has been set, new builds will be created by triggering a build on Netlify's servers; if not, wagtail-netlify will attempt to build the site locally and push it to Netlify.

1. Add `wagtail.contrib.modeladmin` to your `INSTALLED_APPS`
1. Update your project's `urls.py`:
The view will be available to Wagtail administrators as a new `Netlify` menu item.

### Redirects

Including the `wagtailnetlify` URLs will enable a view at /netlify/redirects, which outputs any Wagtail redirects in [Netlify's plain text format](https://docs.netlify.com/routing/redirects/#syntax-for-the-redirects-file). This may be useful if you are using Netlify to host a headless front-end for your Wagtail site.

To enable this view, update your project's `urls.py`:

```python
# in your imports
Expand All @@ -95,11 +102,11 @@ from wagtailnetlify import urls as netlify_urls
url(r"^netlify/", include(netlify_urls)),
```

3. In Netlify's admin interface for your app, add http://yourdomain/netlify/success as a URL to notify for the outgoing webhook on *Deploy succeeded* events (in Settings / Build & deploy / Deploy notifications).
To include the generated redirects in your Netlify-hosted front-end, you should fetch them from the back-end server as part of your front-end build. For example, for a Nuxt site, the build command could be:

The view will be available under `Settings / Deployments` in your site's admin.

Including the `wagtailnetlify` URLs will also enable a view at /netlify/redirects, which outputs any Wagtail redirects in [Netlify's plain text format](https://docs.netlify.com/routing/redirects/#syntax-for-the-redirects-file). This may be useful if you are using Netlify to host a headless front-end for your Wagtail site.
```bash
yarn build && yarn export && wget -O dist/_redirects https://your-wagtail-backend/netlify/redirects
```

## Development

Expand Down
22 changes: 9 additions & 13 deletions setup.py
Original file line number Diff line number Diff line change
@@ -1,37 +1,33 @@
from setuptools import setup, find_packages
from wagtailnetlify import __version__

with open('README.md', 'r') as fh:
with open("README.md", "r") as fh:
long_description = fh.read()

setup(
name='wagtailnetlify',
name="wagtailnetlify",
version=__version__,
description='Deploy Wagtail sites to Netlify',
description="Deploy Wagtail sites to Netlify",
long_description=long_description,
long_description_content_type="text/markdown",
url='https://github.com/tomdyson/wagtail-netlify',
author='Tom Dyson',
author_email='[email protected]',
license='MIT',
url="https://github.com/tomdyson/wagtail-netlify",
author="Tom Dyson",
author_email="[email protected]",
license="MIT",
classifiers=[
"Environment :: Web Environment",
"Framework :: Django",
"Framework :: Wagtail",
"Framework :: Wagtail :: 1",
"Framework :: Wagtail :: 2",
"Intended Audience :: Developers",
"Operating System :: OS Independent",
"Programming Language :: Python",
"Topic :: Internet :: WWW/HTTP",
"Topic :: Internet :: WWW/HTTP :: Dynamic Content",
],
keywords='development',
keywords="development",
packages=find_packages(),
include_package_data=True,
zip_safe=False,
install_requires=[
"wagtail>=1.6",
"wagtail-bakery>=0.3.0"
],
install_requires=["wagtail>=2.0", "wagtail-bakery>=0.3.0"],
)
2 changes: 1 addition & 1 deletion wagtailnetlify/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = "0.7"
__version__ = "0.8"
7 changes: 7 additions & 0 deletions wagtailnetlify/admin_urls.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
from django.urls import re_path
from wagtailnetlify.views import list_deploys, do_deploy

urlpatterns = [
re_path(r"^deployments$", list_deploys, name="list_deploys"),
re_path(r"^deployments/create$", do_deploy, name="do_deploy"),
]
43 changes: 18 additions & 25 deletions wagtailnetlify/management/commands/netlify.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,7 @@
import requests
from django.core.management.base import BaseCommand, CommandError
from django.conf import settings
from wagtailnetlify.models import Deployment

try:
from wagtail.contrib.redirects.models import Redirect
except ImportError: # Wagtail < 2.0
from wagtail.wagtailredirects.models import Redirect
from wagtail.contrib.redirects.models import Redirect


def build_redirects():
Expand All @@ -25,19 +20,18 @@ def build_redirects():

class Command(BaseCommand):

help = "Deploys your baked Wagtail site to Netlify"
help = "Deploys your site to Netlify, or triggers a build"

def write_redirects(self):
""" Redirects are configured in a file called '_redirects'
at the root of the build directory
"""Redirects are configured in a file called '_redirects'
at the root of the build directory
"""
if not hasattr(settings, "BUILD_DIR"):
raise CommandError("BUILD_DIR is not defined in settings")
redirect_file = os.path.join(settings.BUILD_DIR, "_redirects")
redirects_str, count = build_redirects()
fo = open(redirect_file, "w")
fo.write(redirects_str)
fo.close()
with open(redirect_file, "w") as fo:
fo.write(redirects_str)
self.stdout.write("Written %s redirect(s)" % (count))

def trigger_build(self):
Expand All @@ -61,13 +55,13 @@ def deploy(self):
if not netlify_cli:
raise CommandError("NETLIFY_PATH is not defined in settings")

deployment = Deployment()
deployment.save()

command = [netlify_cli, "deploy"]
command.append("--dir={}".format(settings.BUILD_DIR))
command.append("--prod")
command.append('--message="Wagtail Deployment #{}"'.format(deployment.pk))
command = [
netlify_cli,
"deploy",
"--dir={}".format(settings.BUILD_DIR),
"--prod",
'--message="Wagtail Deployment"',
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not add the deployment id here?

]

site_id = getattr(settings, "NETLIFY_SITE_ID", None)
if site_id:
Expand All @@ -81,22 +75,21 @@ def deploy(self):

def add_arguments(self, parser):
parser.add_argument(
"-n", "--no-deploy",
action="store_true",
help="Do not deploy"
"-n", "--no-deploy", action="store_true", help="Do not deploy"
)
parser.add_argument(
"-t", "--trigger-build",
"-t",
"--trigger-build",
action="store_true",
help="Trigger build on Netlify"
help="Trigger build on Netlify",
)

def handle(self, *args, **kwargs):
no_deploy = kwargs["no_deploy"]
trigger = kwargs["trigger_build"]
if trigger:
self.trigger_build()
else:
self.write_redirects()
no_deploy = kwargs["no_deploy"]
if not no_deploy:
self.deploy()
27 changes: 8 additions & 19 deletions wagtailnetlify/models.py
Original file line number Diff line number Diff line change
@@ -1,24 +1,9 @@
from threading import Thread
from django.db import models
from django.core.management import call_command
from django.db import connection
from django.conf import settings
from django.utils.module_loading import import_string

try:
from wagtail.wagtailcore.signals import page_published
except ImportError: # Wagtail < 2.0
from wagtail.core.signals import page_published


class Deployment(models.Model):
netlify_id = models.CharField(max_length=30, null=True)
url = models.URLField(null=True)
deployment_url = models.URLField(null=True)
datetime_started = models.DateTimeField(
auto_now_add=True, help_text="deployment started"
)
datetime_finished = models.DateTimeField("deployment completed", null=True)
from wagtail.core.signals import page_published


def postpone(function):
Expand All @@ -34,8 +19,7 @@ def decorator(*args, **kwargs):
return decorator


@postpone
def deploy(sender, **kwargs):
def deploy():
"""
Trigger a build on Netlify, if NETLIFY_BUILD_HOOK is supplied, or
build static pages, then upload incremental changes to Netlify.
Expand All @@ -46,12 +30,17 @@ def deploy(sender, **kwargs):
else:
call_command("build")
call_command("netlify")


@postpone
def async_deploy(sender, **kwargs):
deploy()
connection.close()


if getattr(settings, "NETLIFY_AUTO_DEPLOY", False) == True:
function_path = getattr(
settings, "NETLIFY_DEPLOY_FUNCTION", "wagtailnetlify.models.deploy"
settings, "NETLIFY_DEPLOY_FUNCTION", "wagtailnetlify.models.async_deploy"
)
function = import_string(function_path)
page_published.connect(function)
63 changes: 63 additions & 0 deletions wagtailnetlify/templates/wagtailnetlify/deploy_listing.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
{% extends "wagtailadmin/base.html" %}

{% block titletag %}Netlify deployments{% endblock %}

{% block content %}
{% block header %}
<header class="nice-padding hasform">
<div class="row header-title">
<div class="left">
<div class="col">
<h1>
<svg class="icon icon-collapse-up header-title-icon" aria-hidden="true" focusable="false">
<use href="#icon-collapse-up"></use>
</svg>
Netlify Deployments</h1>
</div>
</div>
{% block header_extra %}
<div class="right">
<div class="actionbutton">
<a href="deployments/create" class="button bicolor icon icon-plus" title="New deployment">New
Deployment</a>
</div>
</div>
{% endblock %}
</div>
</header>
{% endblock %}

<div>
<div class="row">
<div class="result-list col12">
<table class="listing full-width">
<thead>
<tr>
<th scope="col">Deployment</th>
<th scope="col">Status</th>
<th scope="col">Time taken</th>
<th scope="col">Started at</th>
</tr>
</thead>
<tbody>
{% for deploy in deploys %}
<tr class="odd" data-object-pk="1917">
<td class="nowrap"><a href="{{ deploy.deploy_ssl_url }}">{{ deploy.title }}</a>
(<a href="{{ deploy.admin_url }}">logs</a>)</td>
<td class="nowrap">{{ deploy.state|title }}</td>
<td class="nowrap">
{% if deploy.deploy_time %}
{{ deploy.deploy_time }} seconds
{% else %}
-
{% endif %}
</td>
<td class="nowrap">{{ deploy.created_at_parsed }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
{% endblock %}
9 changes: 3 additions & 6 deletions wagtailnetlify/urls.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
from django.conf.urls import url
from wagtailnetlify.views import success_hook, redirects
from django.urls import re_path
from wagtailnetlify.views import redirects

urlpatterns = [
url(r"^success$", success_hook, name="success_hook"),
url(r"^redirects$", redirects, name="redirect_builder"),
]
urlpatterns = [re_path(r"^redirects$", redirects, name="redirect_builder")]
Loading