Skip to content

Deployment

Overview

Deployments use DeployHQ with a zero-downtime rolling strategy. Each web node is taken out of the Varnish load balancer during deployment, updated, then returned to rotation.

Deployment Flow

Pre-Deployment Checklist

  • [ ] Changes tested on staging (staging.dezeen.com)
  • [ ] Cypress E2E tests pass where applicable
  • [ ] npm run production succeeds locally in _project/_web/
  • [ ] No cache artifacts committed
  • [ ] Database migrations applied manually if needed

Deployment Steps

1. Push to Branch

DeployHQ watches the configured branch (typically master).

bash
git checkout master
git merge develop
git push origin master

2. DeployHQ Pipeline

DeployHQ automatically:

  1. Runs npm run production in _project/_web/ (asset compilation)
  2. For each target node:
    • Runs enable-maintenance.sh (pre-deploy)
    • Syncs files to web node
    • Runs disable-maintenance.sh (post-deploy)

3. Maintenance Scripts

Located in setup/production/deployhq/:

ScriptPurpose
enable-maintenance.shCreates _project/_web/maintenance/ with 503 response
disable-maintenance.shRemoves maintenance directory
enable-maintenance-varnish.shVarnish-specific maintenance
disable-maintenance-varnish.shVarnish-specific restore
test-maintenance.shTest the maintenance setup

How Maintenance Mode Works

  1. Pre-deploy creates _project/_web/maintenance/ directory with index.php returning HTTP 503
  2. Varnish health probe hits /maintenance/ every 5 seconds
  3. On 503 response, Varnish marks the backend as sick and stops routing traffic
  4. After deployment, directory is removed
  5. Varnish probe gets 404, marks backend as healthy, traffic resumes

Post-Deployment Checklist

  • [ ] Site loads correctly (homepage, article, category, search)
  • [ ] Varnish is serving fresh content
  • [ ] Cloudflare cache purged if static assets changed
  • [ ] No errors in wp-content/debug.log
  • [ ] Algolia re-index if search schema changed
  • [ ] Verify key integrations (search, comments, newsletter form)

Branching Strategy

BranchPurpose
developMain development branch
masterProduction-ready code; triggers deployment
feature/*Feature branches, merged to develop
hotfix/*Emergency fixes, merged to both master and develop

Build Commands

bash
# From _project/_web/
npm run dev          # Development build (with source maps)
npm run watch        # Watch mode for development
npm run production   # Production build (minified, no source maps)

Files Excluded from Deploy

From .deployignore:

_project/_data/*
_project/_email/*
_project/_cookiebot/*
_project/_web/node_modules/**
_project/_web/wp-content/themes/2016dezeen/coverage/**

CI/CD

CircleCI

The .circleci/config.yml currently only runs a SonarCloud scan (static analysis). The build and test steps are commented out. Deployments are handled entirely by DeployHQ, not CircleCI.

Cypress Tests

bash
# From project root
npm run cypress:open   # Interactive mode
npm run cypress:run    # Headless mode

Tests run against production by default. Configure cypress.config.js for other environments.

Rollback Procedure

  1. In DeployHQ, select the previous successful deployment
  2. Click "Redeploy" to re-deploy the last known good commit
  3. Alternatively: git revert the problematic commit and push to master

Risks and Gotchas

  • No database migrations: Schema changes must be applied manually via SQL
  • Asset compilation in DeployHQ: If the build fails, the deployment will fail; check DeployHQ logs
  • Varnish probe timing: After removing maintenance mode, there is a 5–15 second delay before traffic resumes (probe interval × window)
  • Cloudflare cache: May need manual purge via the plugin or Cloudflare dashboard if assets changed
  • wp-config.php: Not in version control; changes must be applied manually per node